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

2023-11-20

相关开源库

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)

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>org.xue</groupId>
    <artifactId>netjar</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
<!--    依赖-->
    <dependencies>
<!--        hutool 和 依赖的ftp包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ftpserver</groupId>
            <artifactId>ftpserver-core</artifactId>
            <version>1.2.0</version>
        </dependency>        
<!--       加密相关-->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
<!--        一些工具类-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
<!--            将所有依赖打包到一个jar中-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <finalName>netjar</finalName>
                    <descriptorRefs>
                        <!-- 将依赖的jar包中的class文件打进生成的jar包-->
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <!--
                             Main函数的类,生成的jar包 使用命令执行时的入口函数,
                             如果不需要一个入口. 那就可以随便写一个 唯一的类就行. 不影响
                            -->
                            <mainClass>com.xue.netjar.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <!-- <goal>single</goal>-->
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

为什么要打包成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>MyCode</AssemblyName>
      <AssemblyVersion>1.0.0.0</AssemblyVersion>
      <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>Sm2Util</AssemblyName>
	<AssemblyVersion>1.0.0.1</AssemblyVersion>
	<References>jar/hutool-all-5.6.3.jar;jar/bcprov-jdk15on-1.64.jar;jar/commons-lang3-3.12.0.jar</References>
</IkvmReference>

这种配置文件形式, 估计底层也是调用旧的命令方式去转为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>Exe</OutputType>
		<TargetFramework>net6.0</TargetFramework>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="IKVM" Version="8.2.1" />
	</ItemGroup>

	<ItemGroup>
		<IkvmReference Include="jar/netjar.jar" >
			<AssemblyName>netjar</AssemblyName>
			<AssemblyVersion>1.0.0.4</AssemblyVersion>
		</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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

.Net C# 使用 IKVM 调用 Java 代码 的相关文章

  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • 在 Java 中获取并存储子进程的输出

    我正在做一些需要我开始子处理 命令提示符 并在其上执行一些命令的事情 我需要从子进程获取输出并将其存储在文件或字符串中 这是我到目前为止所做的 但它不起作用 public static void main String args try R
  • Visual Studio Code:如何配置 includePath 以获得更好的 IntelliSense 结果

    我是使用 Visual Studio Code 的完全初学者 我不知道我在做什么 我已经四处搜索 也许还不够 但我找不到像我这样的人如何配置的简单解释c cpp properties json每当我单击带有绿色波浪线下划线的行旁边的黄色灯泡
  • std::forward_as_tuple 将参数传递给 2 个构造函数

    我想传递多个参数以便在函数内构造两个对象 以同样的方式std pair
  • 为什么\0在java中不同系统中打印不同的输出

    下面的代码在不同的系统中打印不同的输出 String s hello vsrd replace 0 System out println s 当我在我的系统中尝试时 Linux Ubuntu Netbeans 7 1 它打印 When I
  • Spring @Cacheable 和 @Async 注解

    我需要缓存一些异步计算的结果 具体来说 为了克服这个问题 我尝试使用 Spring 4 3 缓存和异步计算功能 作为示例 我们采用以下代码 Service class AsyncService Async Cacheable users C
  • 如何分析组合的 python 和 c 代码

    我有一个由多个 python 脚本组成的应用程序 其中一些脚本正在调用 C 代码 该应用程序现在的运行速度比以前慢得多 因此我想对其进行分析以查看问题所在 是否有工具 软件包或只是一种分析此类应用程序的方法 有一个工具可以将 python
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 我可以让 ungetc 取消阻止阻塞的 fgetc 调用吗?

    我想在收到 SIGUSR1 后使用 ungetc 将 A 字符重新填充到标准输入中 想象一下我有充分的理由这样做 调用 foo 时 stdin 中的阻塞读取不会被收到信号时的 ungetc 调用中断 虽然我没想到它会按原样工作 但我想知道是
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • cout 和字符串连接

    我刚刚复习了我的 C 我尝试这样做 include
  • 终结器线程的范围是什么 - 每个应用程序域或每个进程?

    根据我的所有阅读 应该有一个 GC 线程来调用所有终结器 现在的问题是这个 一个 线程的范围是什么 每个进程或每个应用程序域 因为域的整体目的是在一个进程空间中分离并创建 独立 的不同应用程序 I read here http dn cod
  • Java 正则表达式中的逻辑 AND

    是否可以在 Java Regex 中实现逻辑 AND 如果答案是肯定的 那么如何实现呢 正则表达式中的逻辑 AND 由一系列堆叠的先行断言组成 例如 foo bar glarch 将匹配包含所有三个 foo bar 和 glarch 的任何
  • 使用taskkill停止Windows服务

    我需要帮助来使用 C 终止 Windows 服务 现在要终止该服务 请使用以下选项 从命令 sc queryex ServiceName 发现后PID服务的 taskkill pid 1234 exemple f 为了便于阅读 但如果您明白
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo
  • xsi:type 属性搞乱了 C# XML 反序列化

    我使用 XSD exe 根据 XML 架构 xsd 文件 自动生成 C 对象 我正在反序列化 OpenCover 输出 但其中一个部分类未正确生成 这是导致异常的行

随机推荐

  • 为什么在三线城市,Python工程师也能月薪20K?

    Python是这两年编程语言绝对的霸主 你可以发现 几乎所有和程序沾边的人 都在学Python 那么 Python到底有没有用 好在哪里 适合你学吗 今天就来详细分析一下 01 Python究竟能做什么 都说Python易学 究竟好学在哪里
  • Multitor:一款带有负载均衡功能的多Tor实例创建工具

    关于Multitor Multitor是一款带有负载均衡功能的多Tor实例创建工具 Multitor的主要目的是以最快的速度完成大量Tor进程的初始化 并将大量实例应用到我们日常使用的程序中 例如Web浏览器和聊天工具等等 除此之外 在该工
  • 如何做自动化测试

    这个话题比较大 相信大家也都有自己的想法 我在这里写一些我自己的看法 请大家指教 什么叫做自动化测试工程师 首先 会使用自动化测试工具的测试人员不能够称之为完全的自动化测试人员 这类测试人员被称为 工具小子 Script Kid 这个阶段还
  • 关于babel配置使用可选链

    什么是可选链 具体而言它是一种操作符 MDN给出的官方解释是 允许读取位于连接对象链深处的属性的值 而不必明确验证链中的每个引用是否有效 操作符的功能类似于 链式操作符 不同之处在于 在引用为空 nullish null 或者 undefi
  • 第4章 数据库应用系统功能设计与实施

    4 1软件体系结构与设计过程 4 1 1软件体系结构 软件体系结构又称软件架构 软件体系结构 构件 连接件 约束 其中 构件 Component 是组成系统的具有一定独立功能的不同粒度的程序模块 独立程序或软件子系统 是组成软件的系统元素
  • 关于jupyter notebook 更换环境的方法

    一 查看conda现有的环境 打开Anaconda Powershell Prompt 输入以下代码 conda env list 查看环境变量 可以看到如下已经配置的环境变量 二 激活现有环境 在Anaconda Powershell P
  • 使用react-markdown来解析markdown语法

    什么是 react markdown 组件 它是一个基于React的Markdown 编辑器组件 可以对代码进行高亮显示 链接 github网址 react markdown的安装 yarn add react markdown 引入 im
  • 链语BTChat力推“加密+社交” 引领区块链新社交时代

    近些年来互联网的发展日新月异 大数据化 人工智能 物联网这些都在成为人们生活中触手可及的东西 而区块链技能则被认为是继互联网之后最具颠覆性的创新技术 此前区块链技术在金融服务业 游戏 供应链等不同的产业中都有着广泛应用 同样的对于社交平台而
  • wsfuzzer video

    http www neurofuzz com modules software vidz php
  • 14-4_Qt 5.9 C++开发指南_QUdpSocket实现 UDP 通信_UDP组播

    文章目录 1 UDP组播的特性 2 UDP 组播实例程序的功能 3 组播功能的程序实现 4 源码 4 1 可视化UI设计 4 2 mainwindow h 4 3 mainwindow cpp 1 UDP组播的特性 下图简单表示了组播的原理
  • Golang连接Jenkins获取Job Build状态及相关信息

    文章目录 1 连接Jenkins 2 controller 3 module 4 router 5 效果展示 第三方包 gojenkins 方法文档 gojenkins docs 实现起来很简单 利用第三方库 连接jenkins 调用相关方
  • flutter解决键盘顶起页面

    前言 flutter中解决键盘顶起页面的问题 flutter 1 Scaffold resizeToAvoidBottomPadding return Scaffold resizeToAvoidBottomPadding false 解决
  • 使用OpenCV与深度学习从视频和图像中精准识别人脸: Python实践指南

    第一部分 引言与背景 人脸识别已经成为了当代技术领域中最热门和广泛应用的话题之一 从智能手机的解锁功能到机场的安全检查 人脸识别技术无处不在 在这篇文章中 我们将使用Python中的OpenCV库和深度学习模型 深入探讨如何从视频和图像中精
  • js 对数组对象进行排序

    let listData id 1 name 测试1 presenttime 1557883600000 id 2 name 测试2 presenttime 1580751813000 id 3 presenttime 1561448381
  • svn版本号,命令中-r 2和@2的区别

    问题 假设有一个svn repository是 svn 192 168 2 6 project 在版本1 20的svn里 存在 svn 192 168 2 6 project branches branch test 在版本21时 由于br
  • BUUCTF-Web-命令执行-[ACTF2020 新生赛]Exec

    BUUCTF Web 命令执行 ACTF2020 新生赛 Exec 题目链接 BUUCTF 类型 命令注入 知识点 命令拼接符 解题过程 这道题目比较简单 打开发现是一个ping命令执行页面 使用post接受参数 测试命令拼接符 发现未进行
  • CMW500测试设置及问题处理

    测试CATM1需要打开eMTC Auto Mode 最新的U BLOX R510S模块 这里需要设置为RMC模式 设置为eMTC Auto Mode会出现连接后就断开的情况 没法测试 Measure subframe设置为5 不同的band
  • Kubernetes生产实践系列之三十一:Kubernetes基础技术之CPU资源的调度和管理(CFS)

    一 前言 在使用Kubernetes的过程中 我们看到过这样一个告警信息 K8S 告警主题 CPUThrottlingHigh 告警级别 warning 告警类型 CPUThrottlingHigh 故障实例 告警详情 27 throttl
  • android bluetooth UUID蓝牙查询表

    UUID是 Universally Unique Identifier 的简称 通用唯一识别码的意思 对于蓝牙设备 每个服务都有通用 独立 唯一的UUID与之对应 也就是说 在同一时间 同一地点 不可能有两个相同的UUID标识的不同服务 以
  • .Net C# 使用 IKVM 调用 Java 代码

    相关开源库 https github com ikvm revived 版本号 Net 6 JDK 8 IKVM 8 2 1 IKVM 在 8 2 0 版本中新增加 IkvmReference 在 MSBuild 中配置 自动帮你编译jar