• .Net C# 使用 IKVM 调用 Java 代码


    相关开源库

    https://github.com/ikvm-revived

    版本号

    • .Net 6
    • JDK 8
    • IKVM 8.2.1

    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

    Java Maven 部分

    直接创建一个 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    为什么要打包成1个 jar ?

    如果每个依赖都打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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    真实写法, 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这种配置文件形式, 估计底层也是调用旧的命令方式去转为dll ( 可以看到很多老文章都是手动 搞 ikvmc 命令)

    所以我们要打包成一个jar, 不用写一堆 Include , 也不用 写一堆 References 了

    省了不少事情, 直接 写一个 Include , 啥也不用操心了.

    C# 部分

    在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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    保存后, 重新生成下 解决方案.

    此时 写代码 应该已经有 智能提示了.

    最终测试一下

    非常的完美哦. 功能都正常.

    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");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    目录结构

    在这里插入图片描述

    在这里插入图片描述

    题外话

    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

    从某个评论区找到一个替代品, 好像是收费的. 也不开源.

    https://github.com/masesgroup/JCOBridge-Examples

  • 相关阅读:
    nvm下node安装;node环境变量配置
    Java super 关键字使用,它与 this 关键字有什么区别?
    leetcode 665. Non-decreasing Array 非递减数列(中等)
    Day07 SSM第七次笔记---Maven进阶部分学习
    java基础10题
    OpenCV每日函数 结构分析和形状描述符(8) fitLine函数 拟合直线
    《MongoDB入门教程》第11篇 数组运算符
    Linux下安装lrzsz/JDK/Tomcat/MySQL/Git/Maven/Redis
    XLA之HloModule“合并”
    STM32SDIO外设详解
  • 原文地址:https://blog.csdn.net/qq_37214567/article/details/126304703