我试图通过一些例子来理解 jni。我正在尝试使用 jni 获取 java 堆栈跟踪,这就是我正在做的事情
HelloJNI.java
package test.com.jni;
public class HelloJNI {
static {
System.loadLibrary("hello"); // Load native library at runtime
}
private native StackTraceElement[] getStackTraceNative(Throwable throwable);
private native void printStackTraceNative(Throwable throwable);
public static void main(String[] args) {
test();
}
public static void test() {
new HelloJNI().printStackTraceNative(new Throwable()); //Invoke native method
new HelloJNI().getStackTraceNative(new Throwable());
}
}
native 代码(为了简单起见,保留错误处理)
test_com_jni_HelloJNI.c
JNIEXPORT jobjectArray JNICALL Java_test_com_jni_HelloJNI_getStackTraceNative (JNIEnv * env, jobject object, jthrowable exception) {
jclass exceptionClazz = (*env)->GetObjectClass(env, exception);
jmethodID getStackTraceMethod = (*env)->GetMethodID(env, exceptionClazz, "getStackTrace", "()[Ljava.lang.StackTraceElement");
jobjectArray stacktraces = (*env)->CallObjectMethod(env, exception, getStackTraceMethod);
return stacktraces;
}
JNIEXPORT void JNICALL Java_test_com_jni_HelloJNI_printStackTraceNative (JNIEnv * env, jobject object, jthrowable exception) {
jclass exceptionClazz = (*env)->GetObjectClass(env, exception); // can't fail
jmethodID printStackTraceMethod = (*env)->GetMethodID(env, exceptionClazz, "printStackTrace", "()V");
(*env)->CallVoidMethod(env, exception, printStackTraceMethod);
}
现在,在此代码中, native printStackTraceNative
方法可以工作,并且可以打印堆栈跟踪,但是 getStackTraceNative
却不能。当我检查核心转储文件时,它说 java 为 getStackTrace
抛出了异常 java/lang/NoSuchMethodError
。我很困惑,因为我传递给 getStackTraceNative 方法的参数是 throwable 类型,而 throwable 应该具有 getStackTrace 方法。
我在这里可能缺少什么概念,对此的任何帮助表示赞赏。谢谢
最佳答案
您的方法签名错误。在方法签名中,限定类名中的句点被正斜杠替换。因此,getStackTrace
的签名为 ()[Ljava/lang/StackTraceElement;
(另请注意分号)
您可以使用 javap
和 -s
选项从类文件中获取方法签名:
javap -classpath '/path/to/jre/lib/rt.jar' -s java.lang.Throwable
关于java - 如何从java native 接口(interface)(jni)调用getStackTrace方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49989868/