IKVM.NET, un pont entre les mondes du .NET et du Java

IKVM.NET est un framework open source proposant :

  • L’implémentation d’une machine virtuelle Java écrite en .NET. IKVM est donc capable de charger les fichiers .class et d’exécuter l’ensemble des opcodes JAVA.
  • L’implémentation des classes de base du monde Java. En effet, comprendre le bytecode est un élément important, mais sans implémentation des classes courantes du monde JAVA il est impossible d’exécuter la moindre méthode.

Cette implémentation permet comme nous allons le voir:

  • De développer sur la plateforme .NET et d’utiliser les API et jars du monde JAVA.
  • De développer en utilisant le langage JAVA et d’utiliser les API du monde .NET.

IKVM propose deux approches :

  • Une approche dynamique où le bytecode Java est transformé en MSIL .NET à la volée.
  • Une approche statique permettant de transformer un jar en assembly (ce qui est plus performant).

Microsoft avait proposé dans les premières versions du .NET, le langage J#. Mais, ce dernier n’est plus supporté depuis de nombreuses années. De plus, le contexte d'utilisation de ce langage est bien différent de celui d’IKVM. J# proposait néanmoins déjà à l'époque une implémentation des classes de base du Java.

Passons à quelques exemples concrets :

Utilisation de JBarCodeBean dans une application .NET (approche statique).

JBarCodeBean est une célèbre API Java pour générer des codes barres. Nous pouvons télécharger directement le jar original depuis le site.
Grâce à l’outil ikvmc, nous pouvons transformer un jar en un assembly .NET :

ikvmc jbarcodebean-1.2.0.jar -out:jbarcodebean-1.2.0.dll

Examinons cet assembly à l’aide de Reflector :

reflector.png

Le bytecode Java a intégralement été transformé en MSIL. Pour assurer un fonctionnement correct, des références ont été ajoutées (IKVM.*). Comme nous l’avons évoqué, IKVM propose sa propre implémentation des « Java class libraries » sans laquelle rien ne pourrait fonctionner.

Nous allons ensuite créer un projet qui exploite ce nouvel assembly. Notez les namespaces utilisés

using System;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using jbarcodebean;
using net.sourceforge.jbarcodebean.model;
using java.awt.image;

namespace WindowsFormsApplication
{
   public partial class MainForm : Form
   {
       public MainForm()
       {
           InitializeComponent();
       }

       private void Generate_Click(object sender, EventArgs e)
       {
           JBarcodeBean barcode = new JBarcodeBean(BarcodeText.Text, new Code128());
           BufferedImage bcimage = barcode.draw(new BufferedImage(256, 64, BufferedImage.TYPE_INT_RGB));

           PictureBox.Image = bcimage.getBitmap();
       }
   }
}

Et les références de l'assembly:

references.png

Ce code est très simple, mais remarquez la méthode « getBitmap() » proposée par l’implémentation d’IKVM qui facilite la vie et transforme directement une image du monde Java en image du monde .NET.

Voici le résultat :

winforms.png

Exemple de code Java utilisant des API .NET.

Nous allons générer un jar factice (un stub) d’après la définition de mscorlib.dll :

ikvmstub mscorlib.dll –out:mscorlib.jar

Créons ensuite un projet Java, utilisant le namespace System.IO du .NET.

Attention ce projet n’est pas exécutable directement sur une véritable plateforme Java, le stub n’est présent que pour vous permettre de compiler vos classes sans erreurs.

C’est très exactement la technique utilisée par Google pour Android. Ici le Java n’est qu’un langage de « support » (et les jars proposés dans le SDK Android ne sont que des stubs). Le programme ne sera véritablement exécuté que dans une machine virtuelle spécifique (dans notre cas ce sera .NET) avec ses propres opcodes (Dalvik en l’occurrence pour Android) et l’implémentation véritable des classes.

package com.aldheris.ikvm;

import cli.System.IO.Directory;

public class Program {

	public static void main(String args) {
		String files = Directory.GetFiles(".");
	       for(String file : files){ 
	           System.out.println(file);
	       }
	}
}

Bref, dans notre cas, l’environnement d’exécution reste le .NET et IKVM va nous permettre de transformer le bytecode en MSIL, à la volée avec la ligne de commande suivante :

ikvm -jar demo.jar

Et voici le résultat:

output.png

Pour ceux qui l’ignorent encore, la plateforme .NET n’est pas limitée aux environnements Microsoft Windows, et il est parfaitement possible de relancer l’exemple précédent dans un shell linux ou mac grâce à Mono, une implémentation open source du framework .NET avec laquelle IKVM est pleinement compatible.

Quand utiliser ce genre d'outils ?

L’utilisation d’un tel outil paraît intéressante dans certains scénarios de migration ou lorsque des frameworks utiles ne sont pas encore portés dans le monde du .NET.
Il y a bien sûr d’autres moyens de faire communiquer les plateformes Java et .NET (WebServices, REST, etc.), mais cette approche est intéressante par sa facilité de mise en œuvre.
Il est enfin possible d'utiliser IKVM comme "drop-in" JVM pour exécuter du Java sur une machine qui n'est pas équipée.

Compatibilité

Dès que les choses deviennent plus complexes, ces outils demandent un certain niveau d'expertise sur le comportement des plateformes .NET et Java. Attention en particulier au generics qui ne sont pas traités de la même manière suivant la plateforme :

  • Le .NET conserve les informations de généricité dans l'assembly généré.
  • Le Java utilise un mécanisme de conversion des types qui supprime toutes les informations de généricité (Erasure).

Un commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.