【轉載請注明出處】
動機:
充分利用java陣營衆多的類庫
工具:
IKVM――把java bytecode 轉換成IL程式,并提供大部分J2SE 1.4類的.net實作(IKVM.GNU.Classpath.dll)
winrar――提取jar,打包jar
Java IDE(可選)――閱讀源代碼,浏覽類之間的關系,我用的是eclipse
反編譯工具(可選)――沒源代碼時用,主要也是浏覽類與類之間的關系,java反編譯我用的是DJ Java Decompiler,.net用Reflector。
原理:
java也好,.net也好,其執行無非就是運作時 + 庫,把java彙編指令一條一條轉換為IL彙編指令,就可以實作java程式到.net程式的轉換――你可以通過最純正的.net使用方式來使用這些類庫/程式。ikvm實作的就是這樣一個功能。
如果一個java程式調用一大堆java類庫,那麼必須把這些程式和類庫全部轉換成.net的IL格式,這個程式才能執行。
IKVM安裝:
從www.ikvm.net上下載下傳ikvm,解壓縮後就能開始用。
将jar轉換為dll:
運作:ikvmc -target:library ××××.jar
會将jar檔案自動轉換為 ××××.dll
但是,如果jar中引用的類不存在于××××.jar,也不存在于IKVM.GNU.Classpath.dll之中,則會給出警告資訊,該類也不會轉換。這時,需要引用缺少的類所在的dll,格式如下:
ikvmc -target:library -reference:lib1.dll -reference:lib2.dll -reference:lib3.dll jar1.jar
jar的提取:
jar可以用winrar打開,把你想要的目錄或類解壓縮。
把java class檔案打包為jar:
把目錄壓縮成zip格式,把字尾改成jar,OK。
例子:轉換Geotools的main子產品
下面以Geotools的main子產品為例,說明怎樣将jar檔案轉換為IL檔案。
geotools是有10年曆史的GIS中間件。其main子產品有1000多個類,源代碼檔案大小合計9.74M。jar檔案名為gt2-main.jar,2.34M.
步驟1:分析main子產品依賴的類庫,分析類庫間的依賴關系
geotools-main依賴的類庫有:
rt.jar――java的主要的lib
geoapi.jar――OpenGIS一幫人定義的标準geoapi
jai_codec.jar, jai_core.jar,――Java 2D API
JTS-1.4.jar,――Java 拓撲套件,主要用于拓撲分析,可能依賴
vecmath-1.3.jar――vector數學庫
xalan-2.5.1.jar――xml 轉換lib
opengis-legacy-0.1.jar,――忘了幹什麼的,反正和gis有關
units-0.01.jar――不知道是什麼
batik*.jar――SVG lib
mailapi-1.3.jar
步驟2:轉換類庫
先轉換那些沒依賴的庫,比如vecmath-1.3.jar,......
運作:
ikvmc -target:library vecmath-1.3.jar
結果:
Note: output file is "vecmath-1.3.dll"
Note: automatically adding reference to "f:\ikvm-0.20.0.0\ikvm\bin\ikvm.gnu.classpath.dll"
成功轉換成vecmath-1.3.dll。
如果碰上了依賴的庫沒轉換,比如運作:
ikvmc -target:library jai_codec.jar
結果提示有些類找不到:
Note: output file is "jai_codec.dll"
Warning: class "com.sun.image.codec.jpeg.JPEGCodec" not found
Warning: class "com.sun.image.codec.jpeg.JPEGEncodeParam" not found
Warning: class "com.sun.image.codec.jpeg.JPEGImageEncoder" not found
Warning: class "com.sun.image.codec.jpeg.JPEGDecodeParam" not found
Warning: class "com.sun.image.codec.jpeg.JPEGImageDecoder" not found
Warning: class "com.sun.image.codec.jpeg.ImageFormatException" not found
Warning: class "com.sun.image.codec.jpeg.JPEGQTable" not found
Warning: class "sun.security.action.GetPropertyAction" not found
是以對于有依賴關系的庫,需要從最下面那個,大家都依靠它的那個庫轉換起。在這裡就是rt.jar。
ikvmc -target:library rt.jar
慘!!!ikvm彈出錯誤視窗――不是我無能,是rt.jar太狡猾!
怎麼辦?需要從rt.jar中找出所需要的類,将這些類轉換就行了。
用winrar找出需要的類,比如jai_codec需要com.sun.image.codec.jpeg.JPEGCodec,....等8個類,就從rt.jar中找出這些類出來。注意,這些類可能還依賴于别的類,依賴的類也需要找出來,全部打包成一個新的jar,如little_rt.jar。如果有些類在IKVM.GNU.Classpath.dll中已經有了,可以不用提取。
最慘的情況可能是1個類依賴2個類,2個類又依賴8個類,然後又依賴更多的類,這種情況下與其要把這些類提取出來,不如更改這個類,把對外依賴的東東都去掉,全部return null, return 0什麼的。先轉換成功,然後再用.net把這個類重寫就行了。幸運的是這裡沒碰見這情況。
用把little_rt.jar轉換為little_rt.dll,然後運作:
ikvmc -target:library -reference:little_rt.dll jai_codec.jar
OK!成功!
這樣繼續一個jar一個jar的轉換,這些jar會依賴rt.jar中更多的類,需要都提取出來,放在little_rt.jar中,再轉換為little_rt.dll。
就這樣把geoapi.jar,jai_codec.jar, jai_core.jar, JTS-1.4.jar, vecmath-1.3.jar,xalan-2.5.1.jar,opengis-legacy-0.1.jar, units-0.01.jar都轉換成了dll。mailapi-1.3.jar和batik*.jar沒轉換。這兩個直接轉換都沒成功,batik*.jar是一系列jar,之間的關系比較複雜我也搞不清。憑我對geotools的了解, main子產品裡基本沒用到mail,而SVG是以插件形式提供的,在這裡用的也不多。那就不管這兩個,來轉換gt2-main.jar先。
ikvmc -target:library -reference:jai_codec.dll -reference:geoapi.dll -reference:xalan-2.5.1.dll -reference:JTS-1.4.dll -reference:vecmath-1.3.dll -reference:units-0.01.dll -reference:opengis-legacy-0.1.dll -reference:little_rt.dll -reference:jai_core.dll gt2-main.jar
Note: output file is "gt2-main.dll"
Warning: class "org.geotools.ct.CoordinateTransformation" not found
Warning: unable to compile class "org.geotools.renderer.lite.InternalTranscoder"
(missing class "org.apache.batik.transcoder.image.ImageTranscoder")
Warning: class "javax.swing.text.DefaultFormatterFactory" not found
Warning: unable to compile class "org.geotools.ct.CoordinateTransformation$Inverse"
(missing class "org.geotools.ct.CoordinateTransformation")
Warning: class "org.geotools.renderer.style.InternalTranscoder" not found
Warning: class "org.apache.batik.transcoder.TranscoderInput" not found
Warning: class "org.apache.batik.transcoder.SVGAbstractTranscoder" not found
Warning: class "org.apache.batik.transcoder.TranscodingHints$Key" not found
Warning: class "org.apache.batik.transcoder.TranscoderOutput" not found
Warning: class "org.apache.batik.transcoder.TranscodingHints" not found
Warning: class "org.geotools.renderer.lite.InternalTranscoder" not found
Warning: unable to compile class "org.geotools.data.DataTestCase"
(missing class "junit.framework.TestCase")
Warning: class "javax.mail.Session" not found
Warning: class "javax.mail.internet.InternetAddress" not found
Warning: class "javax.mail.Address" not found
Warning: class "javax.mail.internet.MimeMessage" not found
Warning: class "javax.mail.Message" not found
Warning: class "javax.mail.Message$RecipientType" not found
Warning: class "javax.mail.Transport" not found
Warning: class "javax.mail.MessagingException" not found
Warning: class "javax.mail.internet.AddressException" not found
可以看見隻有org.geotools.ct.CoordinateTransformation,org.geotools.renderer.lite.InternalTranscoder,org.geotools.data.DataTestCase這三個類沒轉換成功,其中org.geotools.data.DataTestCase是測試用的,可以不管,剩下兩個類要用到batik中的類,可以按照上述思路把batik轉換為dll,也可重寫這兩個類――剩下的1000個類,已經全部轉換成功,可以在.net平台上用了。
檢驗結果:用reflector打開gt2-main.dll

說明:
1,rt.jar中sun.*;com.*命名空間中的類,IKVM.GNU.Classpath.dll都沒有
2,進行.net開發時需要引用IKVM.GNU.Classpath.dll
3,ikvm的jar->dll轉換可能存在bug,最好把test case也全部轉換過來,測試測試
4,ikvm的jar->dll轉換可能存在性能問題,需要時可進行重構
5,有少量java 文法産生的指令不能直接轉換,會報錯。這是極少量的,我轉換了好幾M的東西了,隻報了2處這種錯。這時候可能需要改動改動java源代碼
本文轉自xiaotie部落格園部落格,原文連結http://www.cnblogs.com/xiaotie/archive/2005/10/10/251724.html如需轉載請自行聯系原作者
xiaotie 集異璧實驗室(GEBLAB)