I have a third party .NET Assembly and a large Java application. I need to call mothods provided by the .NET class library from the Java application. The assembly is not COM-enabled. I have searched the net and so far i have the following:
C# code (cslib.cs):
using System;
namespace CSLib
{
public class CSClass
{
public static void SayHi()
{
System.Console.WriteLine("Hi");
}
}
}
compiled with (using .net 3.5, but the same happens when 2.0 is used):
csc /target:library cslib.cs
C++ code (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();
}
compiled with (using VC 2008 tools, but the same happens when 2003 tools are used):
cl /clr /LD clib.cpp
mt -manifest clib.dll.manifest -outputresource:clib.dll;2
Java code (CallCS.java):
class CallCS {
static {
System.loadLibrary("clib");
}
private static native void callCS();
public static void main(String[] args) {
callCS();
}
}
When I try to run the java class, the Java VM crashes while invoking the method (it is able to load the library):
# # 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
However, if I create a plain cpp application that loads clib.dll and calls the exported function Java_CallCS_callCS, everything is OK. I have tried this on both x86 and x64 environments and the result is the same. I have not tried other versions of Java, but I need the code to run on 1.5.0.
Moreover, if I modify clib.cpp to call only System methods everything works fine even from 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");
}
To wrap up:
- I am ABLE to call System methods from Java -> clib.dll -> mscorlib.dll
- I am ABLE to call any methods from CPPApp -> clib.dll -> cslib.dll
- I am UNABLE to call any methods from Java -> clib.dll -> cslib.dll
I am aware of a workaround that uses 1. above - I can use reflection to load the assmebly and invoke desired methods using only System calls, but the code gets messy and I am hoping for a better solution.
I know about dotnetfromjava project, which uses the reflection method, but prefer not to add more complexity than needed. I'll use something like this if there is no other way, however.
I have looked at ikvm.net also, but my understanding is that it uses its own JVM (written in C#) to do the magic. However, running the entire Java application under its VM is no option for me.
Thanks.