読者です 読者をやめる 読者になる 読者になる

亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

JavaをC#に変態させる。 #hentai_advent

この記事は変態アドベントカレンダー20日目の記事です。

昨日はinatonさんの d:id:motefu:20121219 でした。・・・普通に役に立つんですが。今回の僕の記事どうしましょう。


変態アドベントカレンダー、楽しいですね。しかしながら、みなさん変態の意味を取り違えておいででは・・・?
変態とは、メタモルフォーゼです。あるものの形が何かを通して変わることをさします。例えば、芋虫は蝶に変態しますし、オタマジャクシはカエルに変態しますし、daiksyさんは変態に変態するわけです。あれれ?


そんなわけで、変態させます。Javaを、C#に。

JavaC#に変態させる方法あれこれ。

JavaC#に変態させる方法としてパッと思い浮かぶのははるか昔のVisual StudioについてきたJ#ですね。しかしこれはもはや黒歴史に近いのでここでは触れないでおきましょう。*1*2

Java Native Interfaceを使って使用する方法がCodeProjectに乗っています。

しかしこれは変態させると言うよりも、イヤダイヤダと言っているJavaコードを強引に組み伏せるC#、というな構図しか浮かんで来ません。*3
なんとなく、強引・・・。

やっぱここはC#側がぐっとJava派に寄り添って、優しい心で凍りついたJavaの心を溶かすような、そんなアプローチが求められるわけです。*4

というわけで、IKVM.NETです。

IKVM.NETとは

IKVM.NETとは、JVMを.NET VM上に構築したものです。

・・・さらっと言いましたが、要するにVM on VMなわけで、動作速度はお察しください、になってしまいますが、まさにこれ以上Javaに寄り添ったアプローチなんて考えられるでしょうか。

いわば。

C#『君は何も変わらなくて良い。全て受け止めるから僕のもとにおいでよ。』

Java『///』

といった感じでしょうか。いいですね、いいですね!

IKVM.NETでJavaアセンブリを変態させる

IKVMをダウンロードすると大きく分けて3種類のバイナリが入っています。

  • IKVM:.NET上でjarファイルなどを実行するコマンド。javaコマンドの代わりに使うイメージ。
  • IKVMC:Javaのバイナリファイルを.NETから参照可能なDLLやEXEに変換する。
  • IKVMSTUB:.NETのバイナリファイルをJava上から参照可能なアセンブリに変換する。

それでは、1つずつ見ていきましょう。

IKVM

これがまぁ本体に近いですね。構造的には.NETで実装されたJVMだそうです。ですので、jarファイルを指定してそのまま実行できます。
例えば

public class JavaTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

こんなJavaファイルをコンパイルして作ったjavatest.jarを持って行って、Windwosだとこうします。

>ikvm -jar JavaTest.jar
Hello World!

変態できましたね!

ちなみに同じ事をmono on Macでやると・・・

$ mono ikvm.exe  -jar JavaTest.jar 
Hello World!

より良く変態しているのが分かりますね!!

IKVMC

これが割りと本格的なJava .NETのバイナリ変換器です。と入ってもJavaコード自体はバイナリ変換しておらず(多分)、単純にIKVM上で実行するラッパーを生成します。ですのでIKVM系のライブラリがないと単体では動かない、という事態になります。それではさっきの例でやってみるとこんな感じになります。

>ikvmc JavaTest.jar
IKVM.NET Compiler version 7.2.4630.5
Copyright (C) 2002-2012 Jeroen Frijters
http://www.ikvm.net/

note IKVMC0004: Using main class "javatest.JavaTest" based on jar manifest
note IKVMC0002: Output file is "JavaTest.exe"

これでexeができました。これを普通に起動すると・・・

E:\Desktop\ikvm-7.2.4630.5\bin>JavaTest.exe
Hello World!

となります。

ん?そんなちっちゃいのだとなにがなんだかわからないって?んじゃあもっとでかいのを試してみましょうか・・・。

えーと、ここに良さ気なでかいソースがありますね!!そいじゃ早速・・・

>ikvmc -target:library  groovy-all-2.0.5.jar

とんでもない量の警告が出ますがめげずに待つとgroovy-all-2.0.5.dllというバイナリができます。なんだこれ。

C#プロジェクト作って、作ったdllに参照を貼り、以下の様なコードを書いてやりましょう!

using System;
using groovy.lang;
using jInt = java.lang.Integer;

namespace Groovy.net
{
    class Program
    {
        static void Main(string[] args)
        {
            var binding = new Binding();
            binding.setVariable("foo", new jInt(2));
            var shell = new GroovyShell(binding);
            Console.WriteLine(shell.evaluate(
	        "println 'Hello World'; x = 123; return x * foo"));
            Console.ReadLine();
        }
    }
}

Hello World
246

動いてるように見えなくもない。

・・・昔(1.5くらいの時)はInteractiveShellが起動できたみたいなんですが今(2.0.5)はv無理なので、こちらの記事を参考にしてみました。

IKVMSTUB

これはIKVMCと全く真逆で、.NETコードへのスタブとなるJavaコードを自動生成してくれます。これは結構記事が出ているので、以下あたりを参照してみてください。

・・・ちなみにこれをロードしちゃうと、Javaのくせに.NET環境下でしか立ち上がらないという不思議な状態になります*5

おしまい

IKVM自体は超強力なライブラリで、各種JavaコンポーネントがIKVMを使って.NETポーティングされているプロジェクトはかなりの数あるはずです。Javaが強力な分野は多いですから、性能に配慮しつつ美味しく使っていくべきでしょうね。

あとはガチでJavaC#のコンバートをするものとかもあるのですが時間切れ!ここらへんは個人的にも興味あるので宿題ですね。


次はzerosum_さんです!

*1:というか僕知らないのですよ、J#。本格的にプログラムはじめたのはVS2008以降なので・・・

*2:そもそもJavaではないらしいし。

*3:所謂NTR

*4:NTRより純な感じが好きです。ハイ。

*5:『堕ちた女戦士』といった感じですね