https://github.com/ikvm-revived
IKVM 在 8.2.0 版本中新增加 IkvmReference
(在 MSBuild 中配置. 自动帮你编译jar到dll 和 自动引用dll )
所以本文就用这个了.
不再使用 ikvmc 手动编译, 太繁琐了,
手动输入 ikvm -jar 和 ikvmc 有 java -jar 和 javac 的感觉了.
nuget 第一次安装 ikvm 可能需要点时间,
因为 ikvm 的 dll 比较大. 耐心等待一下.
会保存到 C:\Users\Administrator\.nuget\packages\ikvm\
以后安装同版本的 ikvm 就不用再重复下载了.
首先得有 Java 代码
本文使用
java 的 SM2 加密 (测试自己写的java代码)
和 hutool 中的 简易 FTP 来举例 (测试 第三方依赖 +二级依赖)
SM2 中也使用了 hutool
直接创建一个 Maven 空项目, 开始写代码.
第一部分是 依赖项
第二部分是 打包代码和依赖到一个jar中 (下面有说明为什幺要打包成一个jar)
代码写完后, 在IDEA右侧的 maven 里 双击 package 进行打包.
就会看到输出目录有一个 8.9M 的 netjar.jar
( 如果你只有别人提供的jar包, 也可以 手动执行 jar包的解压和压缩. 把多个jar合成一个 ,
如果只有class文件, 那就得手动创建多层文件夹 和 java 的 package 名称匹配上. 再用命令 压缩为jar)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.xuegroupId>
<artifactId>netjarartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.8.5version>
dependency>
<dependency>
<groupId>org.apache.ftpservergroupId>
<artifactId>ftpserver-coreartifactId>
<version>1.2.0version>
dependency>
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15onartifactId>
<version>1.70version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-simpleartifactId>
<version>1.7.36version>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.12.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-assembly-pluginartifactId>
<version>2.4version>
<configuration>
<appendAssemblyId>falseappendAssemblyId>
<finalName>netjarfinalName>
<descriptorRefs>
<descriptorRef>jar-with-dependenciesdescriptorRef>
descriptorRefs>
<archive>
<manifest>
<addClasspath>trueaddClasspath>
<mainClass>com.xue.netjar.MainmainClass>
manifest>
archive>
configuration>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>assemblygoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
如果每个依赖都打1个包, 那这里会出现9个jar ,
就得在.csproj 配置中 写9遍 指定jar位置 (可能以后会支持指定文件夹吧),
打包成1个就只需要写1遍了.
其实只指定jar位置还不行, IKVM 在执行代码时 , 就会说 找不到 XXX 依赖.
所以你还需要指定依赖 References ,
例子中的 h1 h2 h3 都是 常规的 第三方依赖 , 比如 hutool,
my-code 是 自己写的代码. (java 写的SM2加密)
<ItemGroup>
<IkvmReference Include="files/h1.jar"/>
<IkvmReference Include="files/h2.jar"/>
<IkvmReference Include="files/h3.jar"/>
<IkvmReference Include="my-code.jar">
<AssemblyName>MyCodeAssemblyName>
<AssemblyVersion>1.0.0.0AssemblyVersion>
<References>files/h1.jar;files/h2.jar;files/h3.jar;References>
IkvmReference>
ItemGroup>
真实写法, jar包多了, 那就太痛苦了.
<IkvmReference Include="jar/bcprov-jdk15on-1.64.jar" />
<IkvmReference Include="jar/commons-lang3-3.12.0.jar" />
<IkvmReference Include="jar/hutool-all-5.6.3.jar" />
<IkvmReference Include="jar/Sm2Util.jar" >
<AssemblyName>Sm2UtilAssemblyName>
<AssemblyVersion>1.0.0.1AssemblyVersion>
<References>jar/hutool-all-5.6.3.jar;jar/bcprov-jdk15on-1.64.jar;jar/commons-lang3-3.12.0.jarReferences>
IkvmReference>
这种配置文件形式, 估计底层也是调用旧的命令方式去转为dll ( 可以看到很多老文章都是手动 搞 ikvmc 命令)
所以我们要打包成一个jar, 不用写一堆 Include , 也不用 写一堆 References 了
省了不少事情, 直接 写一个 Include , 啥也不用操心了.
在vs中新建一个名为jar的文件夹, 把 netjar.jar 放进来.
在 .csproj 中添加 IkvmReference , 再添加 Include 为 jar/netjar.jar
指定 AssemblyName ( 编译后的 就是 netjar.dll ) (其他的第三方包不用指定, 会自动识别)
AssemblyVersion 必须是 1.0.0.0 这种 4部分的版本号, 会给dll加上版本信息. (估计内部会根据版本号缓存dll)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>ExeOutputType>
<TargetFramework>net6.0TargetFramework>
<ImplicitUsings>enableImplicitUsings>
<Nullable>enableNullable>
PropertyGroup>
<ItemGroup>
<PackageReference Include="IKVM" Version="8.2.1" />
ItemGroup>
<ItemGroup>
<IkvmReference Include="jar/netjar.jar" >
<AssemblyName>netjarAssemblyName>
<AssemblyVersion>1.0.0.4AssemblyVersion>
IkvmReference>
ItemGroup>
Project>
保存后, 重新生成下 解决方案.
此时 写代码 应该已经有 智能提示了.
非常的完美哦. 功能都正常.
namespace IkvmDemo;
using cn.hutool.core.util;
using cn.hutool.extra.ftp;
using cn.hutool.http;
using cn.hutool.http.server;
using cn.hutool.http.server.action;
using com.xue.netjar; // 自己用java写的 SM2
internal class Program
{
static void Main(string[] args)
{
//*******************
// 测试一下 Java 的 SM2 加密
//var res2 = new Sm2Util()
// .encrypt(
// "我是内容",
// "publicKey太长,省略了.",
// "GBK");
//Console.WriteLine(res2);
//*******************
// 调用一下 java 的 main 方法
//com.xue.netjar.Main.main(args);
//*******************
// 测试一下 hutool 的 IdCard 帮助类. 获取 归属地
//var idCard = "142731195005152222";
//var res = IdcardUtil.getProvinceByIdCard(idCard);
//Console.WriteLine(res);
//*******************
// 启动 Ftp
//SimpleFtpServer.create().addAnonymous("E:/").start();
//**************
// 启动 http服务器
HttpUtil.createServer(8000).addAction("/", new MyAction()).start();
//Console.ReadLine();
}
}
// 有点小遗憾, c#没有 匿名内部类, 只能写一个完整的类, 去实现 hutool 的 Action 接口
public class MyAction : Action
{
public void doAction(HttpServerRequest req, HttpServerResponse res)
{
res.write("hi");
}
}


2022.08.11
https://github.com/ikvm-revived/ikvm-maven
发现作者新开了一个仓库, 这是要给 IKVM 扩展一个 C# 里的 maven 呀
直接 指定一个包名称和版本号, 就能从 maven 仓库 自动拉取依赖. 不用自己折腾本地jar包了.
和 java 用 maven 一模一样.
不过还处在早期 ( 刚写1个月 ), 只实现了基本的 单包拉取 ,
还不会自动分析依赖.
也不能手动指定 之前那个 References 依赖,
执行代码的时候还是会报 找不到xxx依赖
2022.08.11
看 IKVM 的 issues , 好像作者 最近已经开始 兼容 JDK9. (要兼容到最新JDK的节奏? )
这是要兼容 java 所有生态啊 ,太强了…
如果以后 ikvm-maven 完成, 写个包名 直接开始用.
和 C# 用 nuget 一样, 轻轻松松.
那真是无敌了.
2022.08.11
从某个评论区找到一个替代品, 好像是收费的. 也不开源.