IKVM - 0.42.0.3 .NET平台上的Java实现

IKVM是Microsoft .NET Framework和Mono平台上的一个Java实现,他包括以下一些部分:
1. 一个用.NET实现的Java虚拟机
2. Java类库的.NET实现
3. 一些用于Java和.NET之间互操作的工具集
IKVM提供2种主要的方式在.NET平台上运用Java项目。一种是动态方式,即通过IKVM .NET实现的JVM直接运行Java项目,这种方式需要动态的将Java的class或者jar等文件编译成.NET的CIL, 所以启动的时候会比较慢。另外一种是静态方式,即使用IKVM的工具先将class、jar文件编译为.NET的CIL程序集,然后在.NET framework上运行这些程序集,这种方式可以在.NET开发 中直接使用Java的类库
项目组件、程序集介绍参考这里:
1. ikvm.exe,基本对应于java.exe的功能,用于动态运行方式
2. ikvmc.exe,基本对应于javac.exe的功能,用于静态方式
3. ikvmstub.exe,为.NET程序集生成Java class的代理文件,以便在Java中使用.NET程序集的功能

这个项目目前仍然非常活跃,从04年开始到现在一直在开发更新中。对于纯粹基于JDK的Java项目,IKVM目前应该能够处理的比较完善了, 对于使用了Swing和JNI的Java项目,IKVM也有提供支持,但不了解支持程度以及稳定性等方面
IKVM对于2中状况比较有用: 一种Java中的一些项目没有.NET实现的,另一种是某些Java开源项目存在相应的.NET port,但Java的项目很活跃一直在完善更新,而.NET port则停滞了
项目使用的lisence值得考虑,IKVM.OpenJDK.*.dll使用GPL V2,其他的IKVM项目文件使用的lisence应该是BSD之类的 
下面拿StringTemplate做个测试
要求安装有JDK,在Windows环境变量中设置好JAVA_HOME路径(JDK目录),PATH中包含JDK的bin目录
下载安装IKVM,这个步骤非常简单,只需要从IKVM下载最新的bin distribution, 解压到一个目录,将IKVM的bin目录添加到系统环境变量PATH中

1. StringTemplate的Java测试项目
StringTemplate下载最新的Java StringTemplate。如果下载source进行编译的话,可以使用Ant编译(项目中有build.xml文件), 如果使用Eclipse,除了添加antlr的jar引用外,还需要使用antlr生成词法解析器、语法解析器、token等相关的java文件(在target\generated-sources目录下有已经生成好的java文件), 放入到src\org\antlr\stringtemplate\language目录下。编译项目后用Eclipse导出stringtemplate的jar文件
我用的版本为antlr-2.7.7.jar、stringtemplate-3.2.1.jar
用Eclipse建立测试项目,添加antlr-2.7.7.jar、stringtemplate-3.2.1.jar的引用,测试用的java文件如下:
Contact.java

public class Contact {
    private String _name;
    private String _email;
    private int _score;

    public Contact(String name, String email, int score){
        this._name=name;
        this._email=email;
        this._score=score;
    }
    public String getName(){
        return this._name;
    }
    public String getEMail(){
        return this._email;
    }
    public int getScore(){
        return this._score;
    }
    /*
     * StringTemplate不支持在模板中做条件判断,因此下面在model中用属性实现
     */
    public Boolean getIsLevel3(){
        return this._score>1000;
    }
    public Boolean getIsLevel2(){
        return this._score>200 && this._score<=1000;
    }
    public Boolean getIsLevel1(){
        return this._score<=200;
    }
}

sttest.java

import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import org.antlr.stringtemplate.*;
import org.antlr.stringtemplate.language.*;

public class sttest {
    public static void main(String[] args) {
        StringTemplateGroup group =  new StringTemplateGroup("st-test"
                , "E:\\Richie\\java\\workspace\\StringTemplateTest\\lib\\st"
                , DefaultTemplateLexer.class);
        StringTemplate st = group.lookupTemplate("contact_list");
        // a simple attribute
        st.setAttribute("simple_attribute", "Hello StringTemplate!");
        // an object with properties as an attribute
        Contact c = new Contact("Richie", "[email protected]", 100);
        st.setAttribute("contact", c);
        // collections test for Map
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("key1", 111);
        map.put("key2", 222);
        map.put("key3", 333);
        st.setAttribute("items_hashtable", map);
        // collections test for Array
        int[] array = new int[3];
        array[0]=1999;
        array[1]=2888;
        array[2]=3777;
        st.setAttribute("items_array", array);
        // collections test for List
        List<Contact> list = new ArrayList<Contact>();
        list.add(new Contact("Jacky Pan", "[email protected]", 1608));
        list.add(new Contact("RicCC", "[email protected]", 180));
        list.add(new Contact("Richie", "[email protected]", 682));
        st.setAttribute("items_list", list);

        System.out.println(st.toString());
    }
}

直接用Eclipse将其编译为Contact.class、sttest.class文件
测试用的StringTemplate文件如下:
contact_list.st

a simple attribute: $simple_attribute$
$!this is a comment!$
a contact instance:
{ Name="$contact.Name$", EMail="$contact.EMail$" }
Items - Map:
$!
    Remarks:
    The following ST syntax for maps (.NET IDictionary implementations) is not supported
    by StringTemplate C# port (Version 3.2)
!$
map.item_name: { key1 - $items_hashtable.key1$ },{ key3 - $items_hashtable.key3$ }
iterator: $items_hashtable.keys: {{ $attr$ - $items_hashtable.(attr)$ }};separator=","$
Items - Array:
{ $items_array: {value|$value$};separator=","$ }
Items - List:
$items_list: row(seq="odd"), row(seq="even")$

row.st

<tr class="list-$seq$">
       <td>$attr.Name$</td>
       <td>$attr.EMail$</td>
       <td>$attr.score$</td>
       <td>$if(attr.IsLevel3)$Diamond$elseif(attr.IsLevel2)$Golden$else$Standard$endif$</td>
</tr>$\n$$! Remarks: the previous instruction will yield a line feed !$

为了方便,建立一个IKVMTest的目录,将antlr-2.7.7.jar、stringtemplate-3.2.1.jar、Contact.class、sttest.class文件都拷贝到IKVMTest目录中, 在IKVMTest中建立st目录,放入contact_list.st、row.st文件
在命令行进入IKVMTest目录,使用java sttest运行测试项目,结果如下:
     
StringTemplate C#的实现不太完善,上面java的测试项目中就有2个语法,目前StringTemplate C#的3.2版本不支持(或者是bug), 一个是对Map元素的访问方式(即$map_entry.(key)$语法),另一个是$elseif$指令,这个指令在不少情况下会出错。正好借用IKVM项目做这个测试

2. 动态方式运行Java项目
在命令行进入IKVMTest目录,使用ikvm sttest运行测试项目,结果与使用java.exe运行完全一样。也可以看到,ikvm sttest启动时有段时间CPU占用比较高, 此时IKVM在将相关class、jar文件动态编译为CIL代码
ikvm.exe的用法参考这里

3. 静态方式运行Java项目
首先,将antlr-2.7.7.jar转为.NET程序集
ikvmc -out:antlr-2.7.7.dll -target:library -platform:x86 antlr-2.7.7.jar
然后将stringtemplate-3.2.1.jar转为.NET程序集。因为StringTemplate引用了antlr,所以下面的命令必须使用-reference指定antlr的dll文件
ikvmc -out:stringtemplate-3.2.1.dll -target:library -platform:x86 -reference:antlr-2.7.7.dll stringtemplate-3.2.1.jar
最后,将Contact.class、sttest.class转为.NET的exe文件sttest.exe
ikvmc -out:sttest.exe -target:exe -platform:x86 -reference:antlr-2.7.7.dll -reference:stringtemplate-3.2.1.dll -main:sttest Contact.class sttest.class
上面的步骤会在我们测试目录中生成3个文件: antlr-2.7.7.dll、stringtemplate-3.2.1.dll、sttest.exe,这就是从jar、class转换过来的.NET托管程序集了

采用静态方式运行从java转换过来的项目时,需要引用IKVM相关的一些dll文件,我们可以将IKVM的dll注册到全局的GAC中,也可以把相关dll文件拷贝到我们的测试目录
这里我们直接从IKVM的bin目录,将IKVM.OpenJDK.Beans.dll、IKVM.OpenJDK.Charsets.dll、IKVM.OpenJDK.Core.dll、IKVM.OpenJDK.Security.dll、IKVM.OpenJDK.Text.dll、 IKVM.OpenJDK.Util.dll、IKVM.Runtime.dll这几个dll拷贝到我们的测试目录IKVMTest中(我猜测试项目只用到了这些dll),然后在命令行运行sttest.exe,可以看到运行结果与 前面java.exe的运行结果完全一致
ikvmc.exe的用法参考这里

4. 在.NET中使用Java项目
接下来我们用Visual Studio建立一个.NET的测试项目,来测试在.NET下面直接使用从Java转换过来的StringTemplate
我们手工把java的测试项目port成C#的实现。用Visual Studio新建一个IKVM.Test的Console项目,引用步骤 [3. 静态方式运行Java项目] 中生成的antlr-2.7.7.dll、 stringtemplate-3.2.1.dll这2个文件,引用IKVM.OpenJDK.Core.dll文件,项目代码如下:
Contact.cs


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

namespace IKVM.Test

{

    using System;

    public class Contact

    {

        private String _name;

        private String _email;

        private int _score;

<br>

        public Contact(String name, String email, int score)

        {

            this._name = name;

            this._email = email;

            this._score = score;

        }

        public String getName()

        {

            return this._name;

        }

        public String getEMail()

        {

            return this._email;

        }

        public int getScore()

        {

            return this._score;

        }

        //StringTemplate不支持在模板中做条件判断,因此下面在model中用属性实现

        public Boolean getIsLevel3()

        {

            return this._score > 1000;

        }

        public Boolean getIsLevel2()

        {

            return this._score > 200 && this._score <= 1000;

        }

        public Boolean getIsLevel1()

        {

            return this._score <= 200;

        }

    }

}

Program.cs


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

namespace IKVM.Test

{

    using System;

    using org.antlr.stringtemplate;

    using org.antlr.stringtemplate.language;

    class Program

    {

        static void Main(string[] args)

        {

            StringTemplateGroup group = new StringTemplateGroup("st-test"

                , ".\\st", typeof(DefaultTemplateLexer));

            StringTemplate st = group.lookupTemplate("contact_list");

            // a simple attribute

            st.setAttribute("simple_attribute", "Hello StringTemplate!");

            // an object with properties as an attribute

            Contact c = new Contact("Richie", "[email protected]", 100);

            st.setAttribute("contact", c);

            // collections test for Map

            java.util.Map map = new java.util.HashMap();

            map.put("key1", 111);

            map.put("key2", 222);

            map.put("key3", 333);

            st.setAttribute("items_hashtable", map);

            // collections test for Array

            int[] array = new int[3];

            array[0] = 1999;

            array[1] = 2888;

            array[2] = 3777;

            st.setAttribute("items_array", array);

            // collections test for List

            java.util.List list = new java.util.ArrayList();

            list.add(new Contact("Jacky Pan", "[email protected]", 1608));

            list.add(new Contact("RicCC", "[email protected]", 180));

            list.add(new Contact("Richie", "[email protected]", 682));

            st.setAttribute("items_list", list);

            Console.Write(st.toString());

            Console.ReadKey();

        }

    }

}

编译后,将IKVM.Test.exe拷贝到我们的测试目录IKVMTest,运行结果仍然与前面java.exe运行的结果完全一致。可以看到,用这样的方式,对StringTemplate C#版本不支持的语法也能正确执行了

通过上面.NET的测试项目我们可以发现以下几点:
1. 基本数据类型(例如string、int、bool)通过IKVM直接实现互操作
2. 从java转换过来的CIL项目,在.NET中使用时需要遵循java的约定
   例如上面的Contact类,java下的StringTemplate采用反射读取属性值,使用的是java下约定,通过调用getName()、getEMail()等方法 读取,.NET中使用时我们要采用同样的约定才行,而不能定义成.NET的Property
3. JDK的class libraries需要使用IKVM.OpenJDK.Core等IKVM的实现
如果我们在项目中使用IKVM,可能需要通过一些封装手段分离client对IKVM的依赖,例如上面对StringTemplate的测试,我们可以通过接口封装的方法, 将IDictionary转换成java.util.Map,将IList转换成java.util.List等,避免客户端去引用java.util等这些命名空间。某些情况下这个分离可能比较烦

性能对比
性能测试使用的st模板以及给StringTemplate设置属性的代码都跟上面的代码一样,测试结果为
[Java版本] : [StingTemplate的C#版本] : [4. 在.NET中使用Java项目] = [1.5] : [1] : [16.2]
.NET的StringTemplate实现比java版本的性能好一些,在.NET中使用IKVM静态方式性能损失比较大。IKVM存在性能损失是肯定的,但这个差距太大了,可能对于不同项目结果会不一样吧

时间: 2024-10-13 11:36:08

IKVM - 0.42.0.3 .NET平台上的Java实现的相关文章

Android 8.0的平台上,应用不能对大部分的广播进行静态注册

引言在Android 8.0的平台上,应用不能对大部分的广播进行静态注册,也就是说,不能在AndroidManifest文件对有些广播进行静态注册,这里必须强调是有些广播,因为有些广播还是能够注册的.比如,经过测试,对接收Android 开机的广播通过静态注册还是能够正常接收的. 解决办法我们知道广播的注册方式分为两种: 静态注册,也就是说在AndroidManifest文件中对BroadcastReceiver进行注册,通常还会加上action用来过滤. 动态注册,调用Context中的reg

centos7编译安装pure-ftpd-1.0.42

1.下载 wget https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.42.tar.gz 2.安装 tar xvf pure-ftpd-1.0.42.tar.gz cd pure-ftpd-1.0.42 ./configure --prefix=/usr/local/pureftpd --with-everything --with-cookie --with-diraliases --with-extauth

Install tomcat 7.0.42 in ubuntu

frome http://askubuntu.com/questions/339169/how-to-install-tomcat-7-0-42-on-ubuntu-12-04-3-lts Note: visit this question if you want to know why it's not in the repositories: Why don't the Ubuntu repositories have the latest versions of software? Pre

【转】Tomcat7.0.42源代码运行环境搭建

转自:http://tyrion.iteye.com/blog/1903608 以前看过Tomcat5的一部分源代码,当时只看了个大概的启动分析,后来看了<How Tomcat Works>这本书,讲的还行,出版的较早,所以是基于Tomcat4的代码的分析,Tomcat已经release到7了,很多后来添加的特性与新的实 现方式那本书里面没有涉及.下半年业余时间的主要任务就是完成Tomcat7各个我感兴趣的点的系列文章. 先说下我的源码分析的环境搭建吧,用的是eclipse Juno Serv

MT4平台上mql4实现的基于macd指标的智能交易EA

MT4平台上mql4实现的基于macd指标的智能交易EA 屌丝命苦,拼爹拼不过,拼后台没有,技术宅一枚,情商有问题,不会见人说人话见鬼说鬼话,所以在国庆熬着混着,工作也没啥大起色,想想就郁闷,难不成一辈子就只能这样了? 苦思冥想,想得一条路,那就是程序化交易--现在程序化交易正有越来越火的趋势,国外已经程序化了很久,国内各大交易所也正在半掩半遮的开展,卷商.私人公司陆陆续续都在开展,心水啊,想着先研究研究,熟了之后也是碗饭啊,不行就靠着给人写策略也能吃口饭不至于饿死吧,想想还有点小鸡冻啊. 说干

Centos 6.6 x86_64 平台上yum的使用

友情提醒:本文的实验平台vmware 10 + Centos 6.6 X86_64,所述内容中的命令请谨慎使用. -------------------------------------楔子-------------------------------------------------- 胖子法师上次在小酒馆中,关于<grep与正则表达式使用>的阐述为其赢得了几个粉丝.今日在魔法塔中喜滋滋翻看着粉丝来信,一封信中提到在Gnu/Linux os平台上安装程序包的种种不顺,这又勾起了胖子好为人

Linux平台上SQLite数据库教程(二)——C语言API介绍

Linux平台上SQLite数据库教程(二)--C语言API介绍 前言:本文将介绍几个基本的SQLite3数据库的C语言API接口,主要用到两个文件:sqlite3.c.sqlite3.h.源码地址:https://github.com/AnSwErYWJ/SQLite. 打开数据库 1.原型: int sqlite3_open( const char* filename, /* 数据库文件名, 必须为 UTF-8 格式 */ sqlite3** ppDB /* 输出: SQLite 数据库句柄

GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。

1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便地使用所有版本的Android动作栏的设计模式. 对于Android 4.0及更高版本,ActionBarSherlock可以自动使用本地ActionBar实现,而对于之前没有ActionBar功能的版本,基于Ice Cream Sandwich的自定义动作栏实现将自动围绕布局.能够让开发者轻松开发

LeetCode OJ平台上Maximum Subarray题目O(n)复杂度解决方案

原始题目如下,意为寻找数组和最大的子串,返回这个最大和即可. Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [?2,1,?3,4,?1,2,1,?5,4], the contiguous subarray [4,?1,2,1] has the largest sum = 6.