2005年05月13日

 
  令狐冲十四岁那年进入华山,那年岳琳珊八岁,岳不群白天给两人指点剑法,晚上令狐冲给小师妹讲故事哄她入睡。后来,岳不群陆续收了劳德诺,陆大有等徒弟,又忙于修炼紫霞神功,就没有时间指点徒弟。于是他做了一个HUB,从此华山派实现教育电子化,岳不群在网上同时给每个徒弟授课,这种方法很快在五岳剑派内部推广。为了在五岳剑派之间互连,嵩山派掌门左冷禅研制出路由器,使得五岳剑派之间可以互联互通。令狐冲晚上就通过网络给小师妹讲故事。
  很快,岳琳珊已经十六岁,变成了一个亭亭玉立的小姑娘了。令狐冲发现自己的目光总是不由自主的在小师妹身上停留,每次和小师妹在一起的时候,总能听到自己强烈的心跳声,经过了一段时间的茶饭不思后,终于有一天晚上,令狐冲在网上给小师妹发了一首情意绵绵的诗:你是风儿我是沙,你是蜜蜂我是花,你是梳子我是头发,你是牙膏我是牙刷。
  第二天,华山派开例会,令狐冲怀着忐忑不安的心情来到了会议室,发现小师妹红着脸躲在师父后面,而其它的师弟都在偷偷朝自己笑,开完会,一个调皮的师弟就过来叫牙刷师兄,赶紧蒙面逃走。问陆大有,才知道是劳德诺用一个叫NetXRay的工具把自己在网上的大作全抓了出来。令狐冲悔恨万分,于是,闭门研究RFC,成功的研制出LanSwitch。它能够识别设备MAC地址,这样,令狐冲发送给小师妹的数据只有她一个人能够收到。令狐冲晚上可以在网上放心的给小师妹讲故事,偶尔手痒还能敲几句平时心里想又说不出口的话来过瘾,然后,红着脸想象小师妹看到后的表情。
  // LanSwitch是二层交换设备,它可以理解二层网络协议地址MAC地址。二层交换机在操作过程中不断的收集资料去建立它本身的地址表,这个表相当简单,主要标明某个MAC地址是在哪个端口上被发现的,所以当交换机接收到一个数据封包时,它会检查该封包的目的MAC地址,核对一下自己的地址表以决定从哪个端口发送出去。而不是象HUB那样,任何一个发方数据都会出现在HUB的所有端口上(不管是否为你所需)。这样,LanSwitch在提高效率的同时,也提高了系统的安全性。//
  接下来的一年,岳不群大量招收门徒,华山派得以极大的壮大,所使用的LanSwitch也多次级连。但门徒中难免鱼龙混杂,当时华山派一批三、四代弟子崇拜万里独行田伯光,成立了一个田协,经常广播争论比赛八百米还是一千米很合理的问题;第三代弟子中有一个叫xxx的,每天在华山派内部广播xx大法;更让令狐冲受不了的是,随着师父年龄的增大,变得越来越罗嗦,每句话都要重复二十遍,然后在网上广播。令狐冲想和小师妹,陆大有等人专门使用一个广播域,但如果另外使用一个LanSwitch的话,师父肯定不会同意,于是,他修改了LanSwitch的软件,把小师妹,陆大有等人和自己划成一个虚拟网(VLAN),其它人使用另外的VLAN,广播包只在VLAN内发送,VLAN间通过路由器连接。岳不群也深受田协,xxx其害,但为与左冷禅抗争,用人之际,只能隐忍,知道了这件事,大为高兴,但仍为令狐冲私自修改软件一事,罚他到思过崖面壁一年,一年之内不得下山。 在华山派内重新使用VLAN进行子网划分,分为五个子网,师父和师娘,小师妹还有林平之在一个VLAN,xx功弟子用一个VLAN;田协弟子用一个VLAN,其它弟子用一个VLAN,而思过崖上也有单独的一个VLAN。令狐冲到了思过崖,并不难过,终于,世界安静了,依靠左冷禅的路由器,令狐冲还可以每天在网上给小师妹讲故事,聊天。
  // 局域网交换机的引入,使得网络节点间可独享带宽,但是,对于二层广播报文,二层交换机会在各网络节点上进行广播;同时,对于二层交换机无法识别的MAC地址,也必须在广播域内进行广播。当多个二层交换机级连时,二层交换网络上的所有设备都会收到广播消息。在一个大型的二层广播域内,大量的广播使二层转发的效率大大减低,为了避免在大型交换机上进行的广播所引起的广播风暴,需要在一个二层交换网络内进一步划分为多个虚拟网(VLAN)。在一个虚拟网(VLAN)内,由一个工作站发出的信息只能发送到具有相同虚拟网号(VLANID)的其他站点,其它虚拟网(VLAN)的成员收不到这些信息或广播帧。采用虚拟网(VLAN)可以控制网络上的广播风暴和增加网络的安全性。不同虚拟网(VLAN)之间的通信必须通过路由器进行。//
 
  但是幸福永远是短暂的,接下来总是无尽的烦恼。随着整个五岳剑派势力的增大,路由器的速度越来越慢。令狐冲发现每次给小师妹讲故事时,小师妹的回答总是姗姗来迟,而且话也很少,总是"嗯","噢"或者"我听着呢"。终于有一天,路由器再也PING不通的,令狐冲三天没有得到小师妹的消息,对着空空的显示屏,再也忍不住,在一个下着雪的晚上,偷偷下山找小师妹,到了小师妹窗前,发现小师妹正在网上和小林子热烈的聊天,全没注意一边的自己,内心一阵酸痛,回到思过崖,大病一场。病好后潜心研究,终于有一天,做出来一个路由器,这时,令狐冲发现,此时华山派已经有了三十个VLAN,路由器必须为每个VLAN分配一个接口,接口不够用,而且,两个子网内通过路由器的交换速度远远低于二层交换的速度。
  // 二层交换机划分虚拟子网后,就出现了一个问题:不同虚拟子网之间的转发需要通过其它路由器来实现。二层交换机的不同VLAN节点间的转发需要通过路由器设备来实现大大浪费了端口,而路由器的高成本,低效率又使它无法满足大量子网情况下的三层转发需求,三层交换的概念就在这种情况下被提了出来。//
  这天晚上,令狐冲心灰意懒,借酒消愁,这时,一个黑影出现在他的面前,原来是一个道风仙骨的老人,正是风清扬。风清扬听了令狐冲的疑惑,说:路由器接口不够,把路由器做在LanSwitch内部不就可以了;交换速度慢,是因为路由器查找的是网段路由,而LanSwitch直接查MAC对应出端口,当然速度快。为什么不能直接根据IP地址查到出端口呢?令狐冲一听,大为仰慕,但还是不明白,IP地址那么多,而且经常变化,如何能够直接查到出端口呢?风清扬说:
  "你先坐下,让我来问你,华山派有多少弟子?"
  "一万六千左右。"
  "你全知道他们住哪里吗?"
  "不知道。"
  "岳不群要你找一个不知道住哪里的人,如何去找?"
  "查华山派电话号码查询系统,找到他的地址,然后去找他。"
  "如果你回来后再让你找这个人,又如何去找?"
  "如何…. ,查华山派电话号码查询系统,找到他的地址,然后去找他。"
  "你不知道到这个人的地址吗?"
  "知道,但师父说,华山派的地址那么多,而且经常变化,不用知道地址。"
  "岳不群这小子,把徒弟都教成木头了!我问你,你自己认为应该如何找?"
  "直接去找!"
  "好!你这人还不算太苯。那你知道了一个人的地址后,是不是永远记住了?"
  "有的人记住了。其它的都忘了。"
  "为什么忘了?"
  "因为我记不了那么多人,而且一段时间没有去找他。"
  "华山派电话号码查询系统里的地址是如何获得的?"
  "我在空旷处大喊一声他的名字,他听到后就会来找我,告诉我他的地址。"
  风清扬又问了大把类似脑筋急转弯的问题,然后风清扬说:"现在你明白根据IP地址直接查出端口的道理了吗?等到你明白这个道理,你自然会做出三层交换机来",令狐冲仔细回忆了今天的话,终于明白了和二层转发由MAC地址对应到出端口的道理一样,三层转发也可以直接由IP地址对应到出端口,IP地址的路由可以通过ARP来学习,同样需要老化。这样,VLAN间转发除第一个包需要通过ARP获得主机路由外,其它的报文直接根据IP地址就能够查找到出端口,转发速度远远高于路由器转发的速度。抬头看时,风清扬已经走了。
  一年后,令狐冲下思过崖,成功的推出Quidway S8016路由交换机。实现了VLAN间的互通,并且与嵩山,黑木崖等路由器实现互通。
  // 三层交换机是在二层交换机的基础上增加三层交换功能,但它不是简单的二层交换机加路由器,二而是采用了不同的转发机制。路由器的转发采用最长匹配的方式,实现复杂,通常使用软件来实现,。而三层交换机的路由查找是针对流的,它利用CACHE技术,很容易采用ASIC实现,因此,可以大大的节约成本,并实现快速转发。
  很多文章会提及三层交换机和路由器的区别,一般的比较是三层交换机又快又便宜。这些话没有错,但场合是汇聚层。我们看到,在汇聚层,面向三层交换机直接下挂的主机,因为能够获得其主机路由,所以三层交换机能够实现快速查找;而对于通过其它路由器连接多个子网后到达的主机,三层交换机和路由器的处理是一样的,同样采用最长匹配的方法查找到下一跳,由下一跳路由器进行转发。
  因此,通常的组网方式是在骨干层使用GSR,汇聚层使用三层交换机。当然,对于一个小型的城域网,也可以直接拿三层交换机组网,不需要GSR。//

     HSQLDB是一个纯Java的数据库,小巧方便,在做应用程序的demo时会带来很大的方便。我们可以从http://hsqldb.sourceforge.net/下载hsqldb,里面包括源代码,文档以及demo等等。

    IKVM如何获得与安装,我这里就不废话了;framework是1.1版本 ,HSQLDB是最新版本的,IDE是sharpDevelop v1.1.0 build1913。

    我下面要做的工作,就是想测试下是否可以成功把HSQLDB编译成.Net版本的链接库以及生成相关的程序(因为在网上看到了相关的询问,当然网上也有一个C#版本SharpHSQL,有兴趣的可以自己去看看),比如server.exe,webserver.exe等。

    1.进行最简单的测试工作:

   1)ikvmc -target:winexe hsqldb.jar

   成功生成hsqldb.exe(实际上是org.hsqldb.util.SqlTool),在命令行下进行简单测试,没有问题。

    2)ikvmc -target:library hsqldb.jar

   成功生成hsqldb.dll,在#develop中建一工程,引用hsqldb.dll,程序中调用org.hsqldb.util.SqlTool.main(args)和org.hsqldb.util.WebServer.main(args),结果报均报AWT方面的错误,WebServer并没有使用AWT方面的引用;

     3)gnu java 对AWT的支持非常有限,看来要做些简单的修改。忽然想到hsqldb中集成了datamanager,看了看hsql.jar,索性把整个util文件夹删除,重新进行2)的测试工作,成功!

看来只要简单修改就可以把hsqldb port 为hsqldb.net,至于性能如何,我还没有测试过。

In a nutshell, IKVM can be described as a Java Virtual Machine for the .NET CLR. But that brief statement hides a whole new world — IKVM is the first serious option for in-process Java-to-.NET interoperability. Developed primarily by Jeroen Frijters and a small team of contributors, IKVM is an amazing new technology that conclusively breaks down the barriers between Java and .NET. So if you are creating a .NET application, but want to use that cool new Java library that doesn’t yet have a .NET counterpart, here’s a solution for you. Conversely, if you are a Java developer who wants to call a .NET library from Java, IKVM is what you need.

Installation

IKVM requires a .NET runtime to be available on your system. If you are on a Windows operating system, you should have the Microsoft .NET Framework installed. If you are on Linux (or Solaris or OS X), you should have Mono (preferably version 1.0) installed.

Since the IKVM binary distribution consists primarily of .NET assemblies, installing is simple. Just download the binary .zip from the web site, and unzip its content into a directory. Linux users also have the option of downloading a packaged version of IKVM bundled with the Mono 1.0 distribution.

To develop applications with IKVM, you should also have a Java compiler installed. You can use any compiler that produces standard bytecodes, such as Jikes or or the Sun JDK (javac). In Windows, you may wish to install the IKVM .dlls into the Global Assembly Cache to make development easier.

IKVM Components

IKVM essentially consists of a compiler that can transform Java bytecodes into .NET IL representation, either statically or dynamically. It includes the Java standard libraries, in the form of a version of GNU Classpath, pre-compiled into .NET. It also includes JNI providers for Mono and Windows, to enable Java code to access native (C/C++) libraries.

All of the above boils down to three major modes of operation. First is the application ikvm, which can be used as a drop-in replacement for any other JVM. When run in this mode, the Java bytecodes are compiled to .NET IL at runtime, and hence, is known as the dynamic mode of operation.

Second is the ikvmc command, which can be used to convert Java bytecodes into .NET IL. Thus, you can convert a set of Java class files into a .NET assembly.

Since this manner of use statically compiles the Java bytecodes, it’s known as the static mode. Note that while the dynamic mode fully supports the Java classloader semantics, in the static mode, there are necessarily some limitations. Among the issues to watch out for is the fact that all classes are loaded by the bootstrap classloader. See the threads for the gory details. In brief, many Java programs assume this.class.getClassLoader() will return non-null. That, however, is not a valid assumption for classes loaded by the bootstrap loader.

Also, while classloader functionality (such as Class.forName(..)) is available to use, and indeed can be used to load either statically compiled classes or Java bytecode, remember that loading classes out of .NET assemblies that are not referenced directly or indirectly from your application may not work without manual intervention. See the documentation for more detail on this and other hairy issues that arise when two different worlds collide!

The third and final component of IKVM is the ikvmstub compiler, which can be used to generate stubs in Java that wrap .NET classes. With this, you can write Java code that calls into .NET libraries. Note however, that the compiled Java code has to be run on the IKVM JVM. This feature, when coupled with the ikvmc command, makes Java a first-class language to develop applications targeting the .NET CLR

Usage

Let us illustrate all of this with a real-life example. XSL:FO is a W3C recommendation that describes the formatting and flow semantics for paginated presentation in an XML syntax. It is widely used for creating structured source documents for eventual transformation into printed materials. Read "What is XSL-FO?" by G. Ken Holman for an accessible introduction to this technology.

Apache FOP is an open source Java library that can convert xsl:fo files into .pdf format. It was one of the first xsl:fo processors available, and thus over the years has grown into a feature-rich and stable application. As a .NET developer, however, you would have bemoaned the lack of a quality open source FO processor that you could use. This is exactly where IKVM comes in.

To get FOP, you can either build from CVS (get the fop-0_20_2-maintain branch) or download the binary distribution and unzip the package into any directory. For our example, we will use the the normal.fo sample that is included in FOP. To create a .pdf from the xsl:fo file, we would normally use a command such as:

java -cp build/fop.jar:lib/xml-apis.jar:
    lib/xercesImpl-2.2.1.jar:
    lib/avalon-framework-cvs-20020806.jar:
    lib/batik.jar
    org.apache.fop.apps.Fop -fo normal.fo
         -pdf normal.pdf

Note: All of the commands displayed in this article have been broken up to fit a narrow web page, but need to be typed together on one line. All code and commands in this article were written and run on a Linux OS using Mono. To use in Windows, simply change the path and file-separation characters. Also note that you do not need to provide references to assemblies installed in the GAC; the framework will automatically search and resolve such references.

In exactly the same way, we can use IKVM to run FOP via dynamically compiling Java bytecodes to .NET IL:

ikvm -cp build/fop.jar:lib/xml-apis.jar:
    lib/xercesImpl-2.2.1.jar:
    lib/avalon-framework-cvs-20020806.jar:
    lib/batik.jar
    org.apache.fop.apps.Fop -fo normal.fo
         -pdf normal.pdf

And that’s it! You have successfully run a Java program — a reasonably complex program, for which no .NET equivalent exists — within the .NET Framework. However, this is not all. You can now make calls to FOP methods from within a C# program!

First you need to compile the FOP .jar and its dependencies into .NET assemblies. Note that you do not necessarily need to compile all dependencies; IKVM will happily mix .NET and Java by loading some classes from Java bytecodes at runtime.

ikvmc -target:library
     -reference:/usr/lib/IKVM.GNU.Classpath.dll
     lib/xml-apis.jar

ikvmc -target:library
     -reference:/usr/lib/IKVM.GNU.Classpath.dll
     -reference:xml-apis.dll
     lib/xercesImpl-2.2.1.jar

ikvmc -target:library
    -reference:/usr/lib/IKVM.GNU.Classpath.dll
    -reference:xml-apis.dll
    lib/avalon-framework-cvs-20020806.jar

ikvmc -target:library
    -reference:/usr/lib/IKVM.GNU.Classpath.dll
    -reference:xml-apis.dll
    lib/batik.jar

ikvmc -target:library
   -reference:/usr/lib/IKVM.GNU.Classpath.dll
   -reference:xml-apis.dll -reference:batik.dll
   build/fop.jar

This will give you the following .NET assemblies in your current directory:

avalon-framework-cvs-20020806.dll  batik.dll
fop.dll  xercesImpl-2.2.1.dll  xml-apis.dll

Now load up your favorite IDE (for example, VisualStudio in Windows or MonoDevelop on Linux), and add references to these .dlls in your project. And voilà! Your favorite Java project is ready to be used from within .NET programs. For example, the following simple code in C# is used to call FOP’s Driver class to transform an xsl:fo file into a .pdf file:

// Main.cs
using System;
using org.apache.fop.apps;
using ikvm.lang;

class MainClass
{
   public static void Main(string[] args)
   {
    //Load assemblies that are not directly
    //referenced since no CLASSPATH is defined
     AppDomain.CurrentDomain.Load("xercesImpl-2.2.1");
     AppDomain.CurrentDomain.Load("batik");
     java.lang.System.setProperty(
       "javax.xml.parsers.SAXParserFactory",
       "org.apache.xerces.jaxp.SAXParserFactoryImpl");

     java.io.FileOutputStream fs = new
          java.io.FileOutputStream("normal.pdf");
     org.xml.sax.InputSource isrc = new
          org.xml.sax.InputSource("normal.fo");
     Driver driver = new Driver(isrc, fs);
     driver.setRenderer(Driver.RENDER_PDF);
     driver.run();
   }
}

If you have downloaded a binary of FOP 0.20.5, you will need a patched version of fop.jar to successfully run the above code. This is fixed in later CVS versions. The patch is for the bootstrap classloader problem mentioned earlier.

This gives a flavor of what can be done with IKVM. There is, of course, a lot of technology that goes under to covers to achieve this, but that is a topic large enough for another article.

Status

The JVM implementation of IKVM is reasonably complete. It has, for example, full support for reflection, as well as JNI. However, it is well known that to ship a JVM, the most effort has to go into the implementation of the standard libraries. In this regard, IKVM leverages the GNU Classpath project, and therefore has as much support for the standard libraries as GNU Classpath. Thus, IKVM today can run many complex server-side Java libraries. The weak point is the GUI capabilities, not only for the immature (though rapidly improving) implementation of AWT and Swing in GNU Classpath, but also the fact that the AWT peers need to be natively implemented in IKVM. This is where the project is most in need of contributions.

Conclusion

IKVM breaks down the barriers between Java and .NET, probably two of the most significant language platforms of the day. In the sometimes adversarial atmosphere between the two communities, this can be viewed with concern by many Java developers, since the barrier of interoperability against a large installed library base is not longer sufficient to protect your skills. However, one can also see it as an opportunity, increasing the range of target platforms on which the Java programmer may utilize his skills. I think IKVM eventually makes language bigotry the loser, and the winner is that old cliché — "the right tool for the job."

Avik Sengupta is the CTO at Itellix Software Solutions and a contributor to the