工具箱之 IKVM.NET 項目新進展

在各種群里經常討論的一個事情是.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 Framework的編譯器,而 Mono 是 .NET Framework的開源、跨平台版本。2017年IKVM.NET作者決定放棄IKVM.NET的開發工作,從此之後社區里有人分叉了IKVM.NET 並繼續工作,雖然開發工作不是很積極, 不過從2022年3月份至今開發就非常活躍了(//github.com/ikvm-revived/ikvm)[2],現在完全可以支持.NET 6了:

image

IKVM.NET 包括以下三個主要組件:

  1. 在.NET中實現的Java虛擬機:它有一個使用C#.NET開發的JVM,它提供了位元組碼轉換和驗證,類加載等功能,當前支持Java 8,這也是Java 使用最多的版本。
  2. Java類庫的.NET實現:它基本上使用OpenJDK[3]項目來實現JDK庫。
  3. 支持 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 對於各種軟件開發方案非常有用。以下是一些可能性的樣本。

  1. 插入式 JVM 發行版中包含的 IKVM 應用程序是 Java 虛擬機的 .NET 實現。在許多情況下,您可以將其用作 Java 的直接替代品。例如,無需鍵入「java -jar myapp.jar」來運行應用程序,您可以鍵入:ikvm -jar myapp.jar
  2. 在 .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應用程序使用。
  3. 用 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:默認情況下,使用規範定義的規則生成 。要覆蓋此內容,請在此處執行此操作。AssemblyNameAutomatic-Module-Name
  • AssemblyVersion:默認情況下,使用規範定義的規則生成 。要覆蓋此內容,請在此處執行此操作。AssemblyVersionAutomatic-Module-Name
  • DisableAutoAssemblyName:如果禁用 檢測 。trueAssemblyName
  • DisableAutoAssemblyVersion:如果禁用 檢測 。trueAssemblyVersion
  • FallbackAssemblyName:如果未提供或無法計算,請使用此值。AssemblyName
  • FallbackAssemblyVersion:如果未提供或無法計算,請使用此值。AssemblyVersion
  • Compile:可選的以分號分隔的 Java 類路徑項列表,以編譯到程序集中。缺省情況下,如果項目的標識是現有的 JAR 文件或目錄(尚不受支持),則此值是項目的值。支持 MSBuild 客戶端引用多個 JAR 或.class文件。Identity
  • Sources:在文檔生成期間要使用的 Java 源文件的可選分號分隔列表。(尚不支持)
  • References:可選的以分號分隔的其他標識值列表,以指定為對當前標識值的引用。例如,如果依賴於 ,則將兩者都作為項包括在內,但在 元數據上指定 的標識。IkvmReferencefoo.jarbar.jarIkvmReferencebar.jarReferencesfoo.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入門://www.cnblogs.com/shanyou/articles/343118.html

[2]ikvm Github復活倉庫: //github.com/ikvm-revived/ikvm

[3]OpenJDK: //openjdk.java.net/

[4]IkvmReference 設計方案://github.com/ikvm-revived/ikvm/issues/54