在各種群里經常討論的一個事情是.NET 如何調用 Java 的實現,最常見的場景之一就是在加解密方面Java提供的密鑰,C#無法解密, C#中byte范圍是[0,255],而Java中的byte范圍是[-128,127],由于密碼生成器是java所獨有的,其它語言都不支持(IOS,ANDROID,C#,.NET等),既然java這么特立獨行,我們用上的解決方案那么就是Java 范的。
Java和.NET是目前軟件開發的兩種主要技術,Java 8雖然是一種較舊的技術,已經完成了大量的工作。因此,當涉及到可重用性時,在.NET中使用在Java中創建的庫是一種非常普遍的做法。假設您已經在 Java 中開發了一個庫,并且想要在 .NET 項目中使用它,那么 IKVM.NET 有助于在 .NET 中使用 Java 庫。
這就是今天我們要引入的主角 IKVM.NET , IKVM.NET 項目的歷史非常悠久,早在2006 年我在博客上寫了一篇文章 《在.NET平臺上運行Java程序-IKVM.NET入門》[1], IKVM.NET和 Mono 一樣都是.NET 開源史前的社區項目,IKVM 是一個 Java 到 .NET 的編譯器,而 Mono 是 .NET Framework的開源、跨平臺版本。2017年IKVM.NET作者決定放棄IKVM.NET的開發工作,從此之后社區里有人分叉了IKVM.NET 并繼續工作,雖然開發工作不是很積極, 不過從2022年3月份至今開發就非常活躍了(https://github.com/ikvm-revived/ikvm)[2],現在完全可以支持.NET 6了:
IKVM.NET 包括以下三個主要組件:
在.NET中實現的Java虛擬機:它有一個使用C#.NET開發的JVM,它提供了字節碼轉換和驗證,類加載等功能,當前支持Java 8,這也是Java 使用最多的版本。
Java類庫的.NET實現:它基本上使用OpenJDK[3]項目來實現JDK庫。
支持 Java 和 .NET 互操作性的工具:IKVM.NET 包括以下工具:
a) ikvm:Java 虛擬機: 我們可以將其與java.exe(“動態模式”)進行比較。它加載一個類文件并執行其 main 方法,如果我們將類文件名作為參數傳遞,那么它將在可執行 jar 文件中執行 Java 代碼。如果我們將一個jar文件作為參數傳遞,那么它將執行它。
b) ikvmc:將 Java 字節碼編譯為 CIL, 用于將 Java 類和 jar 編譯為 .NET 程序集(“靜態模式”)。此工具將 Java 字節碼轉換為 .NET DLL 和 exe。它將輸入文件中的 Java 字節碼轉換為 .NET DLL。因此,當我們傳遞多個jar文件和類文件時,它將將它們組合在一起并生成單個exe或DLL文件。是 exe 還是 DLL 取決于傳遞的類文件和 jar 文件是否具有 Main 方法。如果他們有一個Main方法,那么它將生成一個exe,否則DLL。
c) ikvmstub:從 .NET 程序集生成 Java 存根類: 它從 .NET 程序集生成存根類文件,以便可以針對 .NET 代碼編譯 Java 代碼。ikvmstub 工具從 .NET 程序集生成 Java 存根。ikvmstub 讀取指定的程序集并生成一個包含 Java 接口和存根類的 Java jar 文件。
IKVM.NET 對于各種軟件開發方案非常有用。以下是一些可能性的樣本。
插入式 JVM?發行版中包含的 IKVM 應用程序是 Java 虛擬機的 .NET 實現。在許多情況下,您可以將其用作 Java 的直接替代品。例如,無需鍵入“java -jar myapp.jar”來運行應用程序,您可以鍵入:ikvm -jar myapp.jar
在 .NET 應用程序中使用 Java 庫,IKVM.NET 包括 ikvmc,一個 Java 字節碼到 .NET IL 轉換器。如果你有一個Java庫,你想在.NET應用程序中使用,然后運行“ikvmc -target:library mylib.jar”來創建“mylib.dll”。例如,Apache FOP項目是一個用Java編寫的開源XSL-FO處理器,廣泛用于從XML源生成PDF文檔。借助 IKVM.NET 技術,Apache FOP可以被任何.NET應用程序使用。
用 Java 開發 .NET 應用程序?IKVM 為您提供了一種用 Java 開發 .NET 應用程序的方法。雖然 IKVM.NET 不包括用于.NET的Java編譯器,但您可以使用任何Java編譯器將Java源代碼編譯為JVM字節碼,然后使用“ikvmc -target:exe myapp.jar”來生成.NET可執行文件。您甚至可以使用包含的 ikvmstub 應用程序在 Java 代碼中使用 .NET API。
支持平臺
.NET Framework 4.6.1 及更高版本
.NET Core 3.1 及更高版本
.NET 5 及更高版本
Java SE 8
IkvmReference
IKVM 包括生成時支持將 Java 庫轉換為 .NET 程序集,這是最近加入的功能特性,具體可以參見?IkvmReference 設計方案[4]。在要引用 Java 庫的項目中安裝包。使用IkvmReference
?來指示您的項目需要哪些 Java 庫。
例:
<ItemGroup><IkvmReference Include="..\..\ext\helloworld-2.0.jar" /></ItemGroup>
輸出程序集將作為項目生成過程的一部分生成。可以向IkvmReference
?其他元數據添加以自定義生成的程序集。
Identity
:項目的標識可以是 a) JAR 文件的路徑 b) 目錄的路徑或 c) 其他不重要的名稱。IkvmReference
AssemblyName
:默認情況下,使用規范定義的規則生成 。要覆蓋此內容,請在此處執行此操作。AssemblyName
Automatic-Module-Name
AssemblyVersion
:默認情況下,使用規范定義的規則生成 。要覆蓋此內容,請在此處執行此操作。AssemblyVersion
Automatic-Module-Name
DisableAutoAssemblyName
:如果禁用 檢測 。true
AssemblyName
DisableAutoAssemblyVersion
:如果禁用 檢測 。true
AssemblyVersion
FallbackAssemblyName
:如果未提供或無法計算,請使用此值。AssemblyName
FallbackAssemblyVersion
:如果未提供或無法計算,請使用此值。AssemblyVersion
Compile
:可選的以分號分隔的 Java 類路徑項列表,以編譯到程序集中。缺省情況下,如果項目的標識是現有的 JAR 文件或目錄(尚不受支持),則此值是項目的值。支持 MSBuild 客戶端引用多個 JAR 或.class文件。Identity
Sources
:在文檔生成期間要使用的 Java 源文件的可選分號分隔列表。(尚不支持)References
:可選的以分號分隔的其他標識值列表,以指定為對當前標識值的引用。例如,如果依賴于 ,則將兩者都作為項包括在內,但在 元數據上指定 的標識。IkvmReference
foo.jar
bar.jar
IkvmReference
bar.jar
References
foo.jar
Debug
:指示是否生成調試符號(不可移植)的可選布爾值。默認情況下,這是根據項目的整體設置確定的。MSBuild 項組定義支持的所有其他元數據。
Reference
IkvmReference
不可傳遞。將其包含在一個項目中并從第二個項目向該項目添加依賴項不會導致在第二個項目上提供相同的引用。而是添加對每個項目的引用。
對于要解析為相同生成的程序集的每個項目,請確保其設置相同。
<ItemGroup><IkvmReference Include="helloworld.jar"><AssemblyVersion>1.0.0.0</AssemblyVersion></IkvmReference><IkvmReference Include="helloworld-2.jar"><AssemblyName>helloworld-2</AssemblyName><AssemblyVersion>2.0.0.0</AssemblyVersion><References>helloworld.jar</References><Aliases>helloworld2</Aliases></IkvmReference></ItemGroup>
相關鏈接:
[1]在.NET平臺上運行Java程序-IKVM.NET入門:https://www.cnblogs.com/shanyou/articles/343118.html
[2]ikvm Github復活倉庫:?https://github.com/ikvm-revived/ikvm
[3]OpenJDK:?http://openjdk.java.net/
[4]IkvmReference 設計方案:https://github.com/ikvm-revived/ikvm/issues/54