我有一个第三方的.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
然而,如果我创建一个简单的cpp应用程序,加载clib.dll并调用导出的函数Java_CallCS_callCS,则一切正常。 我已经在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中调用System方法 -> clib.dll -> mscorlib.dll
- 我能够从CPPApp中调用任何方法 -> clib.dll -> cslib.dll
- 我无法从Java中调用任何方法 -> clib.dll -> cslib.dll
我知道一种使用上述第一种方法的解决方法-我可以使用反射来加载程序集,并仅使用系统调用调用所需的方法,但代码会变得混乱,我希望有更好的解决方案。
我知道dotnetfromjava项目,它使用反射方法,但我不想增加不必要的复杂性。如果没有其他方法,我将使用类似的解决方案。
我也看过ikvm.net,但我的理解是它使用自己的JVM(使用C#编写)来实现这一操作。然而,对我来说,在其VM下运行整个Java应用程序是不可行的选择。
谢谢。