|
并非所有的开发者都清楚,时下最流行的两个程序运行环境(java虚拟机jvm和.net通用语言运行时clr)事实上就是一组共享的类库。不论是jvm还是clr,都为程序代码的执行提供了各种所需的功能服务,这其中包括内存管理、线程管理、代码编译(或java特有的即时编译jit)等等。由于这些特性的存在,在一个操作系统中,如果程序同时运行在jvm和clr两种环境之上,由于任何一个进程都可以加载与之对应的任何共享类库,这使得相应的操作将变得非常繁琐。 然而,当话题讨论到这些问题的时候,大多数开发者都会停下来,向一侧仰着头,非常认真的问道“可是……这样的互操作对我们来说究竟有什么用?” 近些年来,基于java平台的程序开发,一直都有为数众多的api类库和新技术为其提供强大的支持。与此同时,.net的通用语言运行时clr,天生就具备windows操作系统所提供的那些丰富的编程支持。在windows操作系统环境下,常有许多windows编程中易于实现的功能目前却很难使用java语言编程实现,然而有的时候,使用java语言实现特定功能较之windows编程却更为简洁。这是在java编程中,使用java本地接口jni技术实现互操作时的通常看法,同时这对于java的开发者来说也应当是非常熟悉。可能会让开发者感觉有所陌生的,是那些尝试在java虚拟机中实现.net编程语言特性的想法,例如在最新的.net 3.0中,包含工作流、wpf和infocard等广受关注的特性,或是在.net过程中使用java虚拟机提供的工具,比如说部署java语言编写的那些包含复杂业务逻辑的spring组件,或者实现通过asp.net访问jms消息队列这样的功能。 加载动态链接库以及与底层代码托管环境进行交互,是解决互操作问题所面临的两个不同问题,然而,每一项操作都为之提供了标准的应用程序接口来完成这样的功能。举例来说,下面列出的非托管c++代码来自于java本地接口jni的官方文档,目的是利用标准过程(相关的代码句柄在jnihosting子目录里以inprocinterop方案的一部分存在,构建它的最好方法是在命令行里用指向jdk 1.6目录位置的java_home环境变量来操作。 )创建基于java虚拟机的函数调用: 首先来看一款开源的工具包jace(http://jace.sourceforge.net),jace可以简化jni本地调用的互操作过程,其设计目的是使得编写符合jni规范的代码变得轻松简单,特别是对于java虚拟机的bootstrapping引导机制方面。jace的功能相对完善,并且jace为非托管的c++代码提供支持,这样可能意味着我们仍然需要反过头来以windows动态链接库的方式编写各种“不安全”的代码。 另外还有一个叫做ikvm的开源类库,现在已经成为mono项目的一个部分。ikvm在jvm(现在(和可预见的未来)ikvm只会从clr到jvm,不会反过来。)和clr之间搭建了桥梁,为java与.net互操作提供了与其他已提到解决方案不同的实现途径。ikvm的实现并非是将java字节码翻译成cil代码,所以不需要将jvm加载到同一个进程之中。这包含一些有趣的含义,既然java虚拟机没有被加载,在代码中就不需要考虑java虚拟机所需的运行机制:即不需要hotspot技术,不具备jmx监测程序(这意味着没有java控制台来监测你的java代码运行)等等。当然,既然所有的代码将转化为cil语言,就可以利用.net clr通用语言运行时的所有益处,这些功能包括:clr通用语言运行时的jit即时编译技术,clr性能监视器统计等功能。自从ikvm可以执行字节码翻译之后,这样的效果就对于clr的开发者来说就变得相对透明。 然而,我们也可能真的需要加载java虚拟机环境,并且代码的过程代理需要在程序中释放,就像codemesh的juggernet工具(juggernet是java-c++代理工具的.net版本。)生成的代码那样。它提供了两个功能:可以与.net完善集成的java本地接口调用api,使其可以更方便的使用.net环境创建java应用程序,并且提供.net代码生成器产生.net的代理程序,用来配置必须的参数并且执行java对象中定义的函数方法。这样,使用juggernet在.net应用中加载jvm程序的示例代码应该符合下面的过程:
集中化。在许多情况下,我们希望特定资源(比方说代码中的数据库序列标识符)只存在于一个且仅此一个进程之中,来避免复杂的进程间代码同步的实现。 可靠性。较少的硬件相关性,以及整个系统单一的硬件损耗,使得系统很少会有受到攻击的可能性。 结构化要求。在某些情况下,现有的结构化模型将要求所有程序处理过程替代已有的处理过程,比如说,应用程序的现有用户接口如果使用asp.net编写,并且应用程序部分的互操作性,用以实现为ejb消息驱动bean在jms消息队列中的消息传送处理过程。则在本地程序中传送消息给java服务,并且仅是释放消息到jms队列之中,这样的过程就显得有些多余,特别是在假定jms客户端代码非常简洁的时候,程序实现代价较高。将jms的客户端代码放入asp.net进程之中(codemesh为juggernet代理实现jms消息客户端提供了特别的版本),来实现与现有程序架构保持一致的简洁途径。 此外,并非是所有的互操作解决方案都将通过in-proc方法来实现,但其中一些会使用这样的方法,并且开发者无需害怕这样的想法,即便是提供这些操作的工具有着非常大的使用价值。 关于作者 ted neward是大规模企业应用系统方面的独立咨询人。也是java、.net和xml服务相关主题的会议上的演讲人,致力于java与.net的互操作技术。在java与.net方面,他曾撰写过几本广受认可的书籍,其中包括最近出版的《高效企业级java开发》一书。 资源 "the java native interface" (liang) "java native interface" (gordon) the jni page at the java se website (http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html) "customizing the common language runtime" (pratschner) "shared source cli" (stutz, neward, shilling) the c++/cli language specification (ecma international)
|