我有一个第三方 .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 在调用该方法时崩溃(它能够加载库):
#
# An unexpected error has been detected by Java Runtime Environment:
#
# Internal Error (0xe0434f4d), pid=3144, tid=3484
#
# Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode, sharing windows-x86)
# Problematic frame:
# C [kernel32.dll+0x22366]
#
...
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
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 以仅调用系统方法,即使在 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# 编写)来实现魔法。然而,在虚拟机下运行整个 Java 应用程序对我来说是不可能的。
Thanks.