在各种群里经常讨论的一个事情是.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