工具箱之 IKVM.NET 專案新進展

微軟技術棧 發表於 2022-06-29
.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月份至今開發就非常活躍了(https://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入門: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