Java JNIEnv 分段错误
我正在使用它们之间的本机库编写一些 Java<->.NET 互操作代码,到目前为止,一切进展顺利。
但是由于某种原因我无法在 JNIEnv 下运行任何方法。
System::String^ JNIStringToNet(JNIEnv * env, jstring js)
{
const char *buf = env->GetStringUTFChars(js, 0); // segfault
现在我可以来回传递变量并进行所有其他类型的通信,所以我想我没有正确初始化它或其他东西。
我像这样加载它:(
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
我更喜欢 Native.loadLibrary,因为它似乎让我可以更轻松地做更多事情,例如多个库之间的类共享以及动态地从 JVM 中取消挂钩和重新挂钩)。
编辑:
认真的任何方法:
std::cout << "Getting version:" << std::endl;
std::cout << env->GetVersion() << std::endl;
获取版本:(
段错误)
关于 JNIEnv 会对每个方法产生段错误有什么想法吗?这应该是由 JVM 设置的,对吗?
编辑2:
这是一个Java应用程序,它调用一个C++库,该库将与.NET库交互(因此它是一个CLR编译的C++库,如果这有什么区别的话),以限制任何外部因素我什至没有调用 .NET DLL,而只是将传入的字符串转换回来(或者好吧......尝试)。
例如,来自 Java:
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
this.Lib.myCPPMethod(); // Segmentation fault during this call, JVM crashes.
好奇是否是 CLR 导致了它:禁用了 clr 编译并剥离了与 CLR 相关的所有内容,但仍然如此。
编辑3:
将其转储:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000000000, pid=1596, tid=7248
#
# JRE version: 6.0_23-b05
# Java VM: Java HotSpot(TM) 64-Bit Server VM (19.0-b09 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C 0x0000000000000000
是的,看起来 JVM 由于某种原因没有给我内存访问权限。
编辑4:
实际调用:
JNIEXPORT jstring JNICALL Query(JNIEnv * env, jobject jobj, jstring start, jstring end)
{
std::cout << "Getting version:" << std::endl;
jint j = env->GetVersion();
return jstring("test");
}
编辑5:
与System.loadLibrary一起使用:
JNIEXPORT void JNICALL Java_LibTest_T(JNIEnv *env, jobject jobj)
{
std::cout << "Getting version:" << std::endl;
jint j = env->GetVersion();
std::cout << j << std::endl;
}
输出:
java -Djava.library.path="(dir)\lib\64" EntryPoint
Getting version:
65542
Ack!我的意思是取得了一些进展,但我无法从 JVM 中卸载 System.loadLibrary 中加载的库,可以吗?
我基本上需要能够从 JVM 中解开这些库并将它们交换出来,最重要的是它们都需要“共享”单个类并能够在运行时绑定到该类......这就是为什么我选择了 Native.loadLibrary。
目前我这样做:
加载DLL:
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
取消挂钩:
this.Lib = null;
Runtime.getRuntime().gc(); // Force the JVM to drop it immediately.
类我将它们全部加载到:
public interface LibHandler extends Library{
void T();
}
有什么方法可以与System.loadLibrary进行类似的工作吗?
编辑6:
请随意称我为笨蛋,我正在使用JNA,不是 JNI,这是完全不同的,也是我问题的一个巨大根源......在那里有办法用 JNI 做到这一点吗?或者我可以让 JNIEnv 以某种方式向 JNA 注册吗?我猜我可以从 C++ 库中删除 JNI 并直接使用 wstrings 吗?
我明天会回来处理这个问题。
I'm in the process of doing some Java<->.NET interop code using a native library between them, so far things are going fairly well.
However for some reason I cannot run any methods under JNIEnv.
System::String^ JNIStringToNet(JNIEnv * env, jstring js)
{
const char *buf = env->GetStringUTFChars(js, 0); // segfault
Now I can pass variables back and forth and do all other kinds of communication, so I'm figuring I haven't initialized this correctly or something.
I'm loading it like this:
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
(I prefer Native.loadLibrary because it seems to allow me to do more with it easier, such as class sharing between multiple libraries and unhooking and rehooking it from the JVM on the fly).
Edit:
Seriously any method:
std::cout << "Getting version:" << std::endl;
std::cout << env->GetVersion() << std::endl;
Getting version:
(segfault)
Any ideas on wht JNIEnv would segfault for every method? This should be set up by the JVM, correct?
Edit 2:
This is a Java application that is calling a C++ library that will interface with a .NET library (so it's a CLR compiled C++ library, if that makes any difference), to limit any external factors I'm not even calling the .NET DLL but just converting strings that come in back out (or well... trying).
So for example from Java:
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
this.Lib.myCPPMethod(); // Segmentation fault during this call, JVM crashes.
Curious if it was the CLR that was causing it: Disabled clr compilation and stripped everything out that was CLR related, still does it.
Edit 3:
Got it to dump:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000000000, pid=1596, tid=7248
#
# JRE version: 6.0_23-b05
# Java VM: Java HotSpot(TM) 64-Bit Server VM (19.0-b09 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C 0x0000000000000000
So yeah, looks like the JVM isn't giving me memory access for some reason.
Edit 4:
Actual call:
JNIEXPORT jstring JNICALL Query(JNIEnv * env, jobject jobj, jstring start, jstring end)
{
std::cout << "Getting version:" << std::endl;
jint j = env->GetVersion();
return jstring("test");
}
Edit 5:
Works with System.loadLibrary:
JNIEXPORT void JNICALL Java_LibTest_T(JNIEnv *env, jobject jobj)
{
std::cout << "Getting version:" << std::endl;
jint j = env->GetVersion();
std::cout << j << std::endl;
}
Output:
java -Djava.library.path="(dir)\lib\64" EntryPoint
Getting version:
65542
Ack! I mean some headway, but I can't unload libraries from the JVM that are loaded in System.loadLibrary can I?
I basically need to be able to unhook these libraries from the JVM and swap them out, on top of that they all need to "share" a single class and be able to be bound to the class at runtime... which is kinda why I went with Native.loadLibrary.
Currently I do this:
Load the DLL:
this.Lib = (LibHandler)Native.loadLibrary(this.Name, LibHandler.class);
Unhook it:
this.Lib = null;
Runtime.getRuntime().gc(); // Force the JVM to drop it immediately.
Class I load them all into:
public interface LibHandler extends Library{
void T();
}
Any way to work similarly with System.loadLibrary?
Edit 6:
Feel free to call me dumb, I'm using JNA, NOT JNI, which is completely different and a huge source of my problems.... is there a way to do this with JNI? Or can I get JNIEnv to register with JNA somehow? I'm guessing I can drop JNI from the C++ library and straight up use wstrings?
I'll get back with this tomorrow.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
嗯,我感觉很糟糕。
Native.loadLibrary == JNA。
System.loadLibrary == JNI。
JNA 的目的是不需要任何关于 JVM 环境的实际知识,因此您可以按原样运行本机库,因此您可以使用 char* 代替 jstring...
Well I feel bad.
Native.loadLibrary == JNA.
System.loadLibrary == JNI.
The purpose of JNA is to not require any real knowledge of the JVM environment, so you can run native libraries as is, so instead of jstring you can use char*...