zoukankan      html  css  js  c++  java
  • IKVM

    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文件(在targetgenerated-sources目录下有已经生成好的java文件), 放入到srcorgantlrstringtemplatelanguage目录下。编译项目后用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", "Richie-test@gmail.com", 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", "JackyPan-test@gmail.com", 1608)); list.add(new Contact("RicCC", "RicCC-test@gmail.com", 180)); list.add(new Contact("Richie", "Richie-test@gmail.com", 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>$
    $$! 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", "Richie-test@gmail.com", 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", "JackyPan-test@gmail.com", 1608));
                list.add(new Contact("RicCC", "RicCC-test@gmail.com", 180));
                list.add(new Contact("Richie", "Richie-test@gmail.com", 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存在性能损失是肯定的,但这个差距太大了,可能对于不同项目结果会不一样吧 

  • 相关阅读:
    leetcode101
    leetcode345
    leetcode27
    leetcode342
    leetcode198
    2019-7-29-NetBIOS-计算机名称命名限制
    2019-7-29-NetBIOS-计算机名称命名限制
    2018-5-28-win10-uwp-动态修改ListView元素布局
    2018-5-28-win10-uwp-动态修改ListView元素布局
    2018-11-19-win10-uwp-使用-Matrix3DProjection-进行-3d-投影
  • 原文地址:https://www.cnblogs.com/Alex80/p/4276131.html
Copyright © 2011-2022 走看看