Chamando o assembly .NET de Java: falhas da JVM
Eu tenho um .NET Assembly de terceiros e um grande aplicativo Java. Eu preciso chamar mothods fornecidos pela biblioteca de classes .NET do aplicativo Java. O assembly não está habilitado para COM. Eu pesquisei na net e até agora eu tenho o seguinte:
Código c # (cslib.cs):
using System;
namespace CSLib
{
public class CSClass
{
public static void SayHi()
{
System.Console.WriteLine("Hi");
}
}
}
compilado com (usando o .net 3.5, mas o mesmo acontece quando o 2.0 é usado):
csc /target:library cslib.cs
Código 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();
}
compilado com (usando ferramentas do VC 2008, mas o mesmo acontece quando ferramentas 2003 são usadas):
cl /clr /LD clib.cpp
mt -manifest clib.dll.manifest -outputresource:clib.dll;2
Código Java (CallCS.java):
class CallCS {
static {
System.loadLibrary("clib");
}
private static native void callCS();
public static void main(String[] args) {
callCS();
}
}
Quando tento executar a classe java, a VM Java falha ao invocar o método (é capaz de carregar a biblioteca):
# # 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
No entanto, se eu criar um aplicativo cpp simples que carregue o clib.dll e chame a função exportada Java_CallCS_callCS, tudo estará OK. Eu tentei isso em ambientes x86 e x64 e o resultado é o mesmo. Eu não tentei outras versões do Java, mas eu preciso que o código seja executado no 1.5.0.
Além disso, se eu modificar o clib.cpp para chamar apenas os métodos do sistema, tudo funciona bem, mesmo a partir do 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");
}
Para finalizar:
Eu sou capaz de chamar métodos do sistema de Java -> clib.dll -> mscorlib.dllEu sou capaz de chamar qualquer método de CPPApp -> clib.dll -> cslib.dllEu sou incapaz de chamar qualquer método de Java -> clib.dll -> cslib.dllEstou ciente de uma solução que usa 1. acima - eu posso usar reflexão para carregar o assmebly e invocar métodos desejados usando apenas chamadas do sistema, mas o código fica confuso e estou esperando por uma solução melhor.
Eu sei sobre o projeto dotnetfromjava, que usa o método de reflexão, mas prefere não adicionar mais complexidade do que o necessário. Vou usar algo assim, se não houver outra maneira, no entanto.
Eu olhei ikvm.net também, mas meu entendimento é que ele usa sua própria JVM (escrita em C #) para fazer a mágica. No entanto, a execução de todo o aplicativo Java em sua VM não é uma opção para mim.
Obrigado.