我有一个第三方 .NET 程序集和一个大型 Java 应用程序。我需要从 Java 应用程序调用 .NET 类库提供的方法。该程序集未启用 COM。我已经搜索了网络,到目前为止我有以下内容:
C# 代码(cslib.cs):
using System;
namespace CSLib
{
public class CSClass
{
public static void SayHi()
{
System.Console.WriteLine("Hi");
}
}
}
编译(使用 .net 3.5,但使用 2.0 时也会发生同样的情况):
csc /target:library cslib.cs
C++ 代码(clib.cpp):
#include <jni.h>
#using <CSLib.dll>
using namespace CSLib;
extern "C" _declspec(dllexport) void Java_CallCS_callCS(JNIEnv* env, jclass cls) {
CSLib::CSClass::SayHi();
}
编译时使用(使用 VC 2008 工具,但使用 2003 工具时也会发生同样的情况):
cl /clr /LD clib.cpp
mt -manifest clib.dll.manifest -outputresource:clib.dll;2
Java 代码(CallCS.java):
class CallCS {
static {
System.loadLibrary("clib");
}
private static native void callCS();
public static void main(String[] args) {
callCS();
}
}
当我尝试运行 java 类时,Java VM 在调用该方法时崩溃(它能够加载库):
# # Java Runtime Environment 检测到意外错误: # # 内部错误 (0xe0434f4d), pid=3144, tid=3484 # # Java VM:Java HotSpot(TM) Client VM(10.0-b19混合模式,共享windows-x86) # 有问题的框架: #C [kernel32.dll+0x22366] # ... Java 框架:(J=编译的 Java 代码,j=解释的,Vv=VM 代码) j CallCS.callCS()V+0 j CallCS.main([Ljava/lang/String;)V+0 v ~StubRoutines::call_stub
但是,如果我创建一个加载 clib.dll 并调用导出函数 Java_CallCS_callCS 的普通 cpp 应用程序,则一切正常。我在 x86 和 x64 环境中都试过了,结果是一样的。我没有尝试过其他版本的 Java,但我需要代码在 1.5.0 上运行。
此外,如果我修改 clib.cpp 以仅调用 System 方法,即使从 Java 也一切正常:
#include <jni.h>
#using <mscorlib.dll>
using namespace System;
extern "C" _declspec(dllexport) void Java_CallCS_callCS(JNIEnv* env, jclass cls) {
System::Console::WriteLine("It works");
}
总结一下:
- 我能够从 Java -> clib.dll -> mscorlib.dll 调用系统方法
- 我可以从 CPPApp -> clib.dll -> cslib.dll 调用任何方法
- 我无法从 Java -> clib.dll -> cslib.dll 调用任何方法
我知道使用上述 1. 的解决方法 - 我可以使用反射来加载程序集并仅使用系统调用调用所需的方法,但是代码变得混乱,我希望有一个更好的解决方案。
我知道 dotnetfromjava 项目,它使用反射方法,但不希望增加比需要更多的复杂性。但是,如果没有其他方法,我会使用类似的东西。
我也看过 ikvm.net,但我的理解是它使用自己的 JVM(用 C# 编写)来发挥作用。但是,在其 VM 下运行整个 Java 应用程序对我来说是没有选择的。
谢谢。