一般使用 java JNI GetFieldID 和 JNI
working with java JNI GetFieldID and JNI in general
我似乎对JNI没有太多运气。我正在等待我买的一本书到货,但现在它是反复试验。
evaluatorNew() 只是创建一个新的 Evaluator() 对象,创建一个新的 CPtr()类对象,如 Java 端所述,将我们的 Evaluator() 对象的指针分配给 CPtr 的 'peer' 成员,并返回新的 CPtr jobject。
JNIEXPORT jobject JNICALL Java_com_starlon_libscriptable_UtilsEvaluator_evaluatorNew(
JNIEnv *env, jclass clazz)
{
int foo = 1;
while(foo);
Evaluator *eval = new Evaluator();
jobject obj;
jclass tempClass;
tempClass = env->FindClass("com/starlon/libscriptable/CPtr");
obj = env->AllocObject( tempClass );
if (obj)
{
env->SetLongField( obj, env->GetFieldID( tempClass, "peer", "J" ), (jlong)eval);
}
return obj;
}
这是保存指针的 Java 类。这就是"env->FindClass()"所调用的内容。
public class CPtr
{
/* Pointer value of the real C pointer. Use long to be 64-bit safe. */
private long peer;
protected long getPeer()
{
return peer;
}
/* No-args constructor. */
CPtr() {}
}
没有堆栈跟踪可言,如下所示。
(gdb) bt
#0 0xafd15ca8 in __libc_android_abort ()
from /home/scott/workspace/StarVisuals/StarVisuals/obj/local/armeabi-v7a/libc.so
#1 0x00000008 in ?? ()
Backtrace stopped: frame did not save the PC
下面是 gdb 逐步执行上述 JNI 函数的转储:
0x80805258 in Java_com_starlon_libscriptable_UtilsEvaluator_evaluatorNew (env=0xabd8,
clazz=0x40715698) at jni/libscriptable//evaluator.cpp:85
85 while(foo);
Current language: auto; currently c++
(gdb) set foo = 0
(gdb) s
[New Thread 11226]
[Switching to Thread 11226]
87 Evaluator *eval = new Evaluator();
(gdb) u
92 tempClass = env->FindClass("com/starlon/libscriptable/CPtr");
(gdb) u
94 obj = env->AllocObject( tempClass );
(gdb) u
95 if (obj)
(gdb) s
97 env->SetLongField( obj, env->GetFieldID( tempClass, "peer", "J" ), (jlong)eval);
(gdb) s
_JNIEnv::GetFieldID (this=0xabd8, clazz=0x40715910, name=0x8080a134 "peer", sig=0x8080a13c "J")
at /opt/android-ndk-r7b/platforms/android-9/arch-arm/usr/include/jni.h:708
708 { return functions->GetFieldID(this, clazz, name, sig); }
(gdb) print functions
$1 = (const JNINativeInterface *) 0xaca9dd68
(gdb) print this
$2 = (_JNIEnv * const) 0xabd8
(gdb) print clazz
$3 = (jclass) 0x40715910
(gdb) print name
$4 = 0x8080a134 "peer"
(gdb) print sig
$5 = 0x8080a13c "J"
(gdb) print *functions
$6 = {reserved0 = 0x0, reserved1 = 0x0, reserved2 = 0x0, reserved3 = 0x0, GetVersion = 0xaca43385,
DefineClass = 0xaca43355, FindClass = 0xaca4773d, FromReflectedMethod = 0xaca47719,
FromReflectedField = 0xaca476f5, ToReflectedMethod = 0xaca476b9, GetSuperclass = 0xaca44801,
IsAssignableFrom = 0xaca4450d, ToReflectedField = 0xaca4767d, Throw = 0xaca43331,
ThrowNew = 0xaca47655, ExceptionOccurred = 0xaca447b1, ExceptionDescribe = 0xaca4761d,
ExceptionClear = 0xaca43315, FatalError = 0xaca44d99, PushLocalFrame = 0xaca475c1,
PopLocalFrame = 0xaca47561, NewGlobalRef = 0xaca44ac1, DeleteGlobalRef = 0xaca4502d,
---Type <return> to continue, or q <return> to quit---q
SetByteFieldQuit
(gdb) print functions->GetFieldID
$7 = (jfieldID (*)(JNIEnv *, jclass, const char *, const char *)) 0xaca47435
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0xaca4cd0c in ?? ()
(gdb) bt
#0 0xafd15ca8 in __libc_android_abort ()
from /home/scott/workspace/StarVisuals/StarVisuals/obj/local/armeabi-v7a/libc.so
#1 0x00000008 in ?? ()
Backtrace stopped: frame did not save the PC
(gdb) quit
这是 jni.h 的第 708 行:
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
{ return functions->GetFieldID(this, clazz, name, sig); } // 708
有什么帮助吗?如果我需要澄清任何事情,请告诉我。
你的代码是理所当然的。您需要检查每个(我的意思是每个)JNI 调用的结果,通过查找异常并在遇到异常时中止。你不能像这样堆叠函数调用Lisp风格,并希望它们都返回可用的值。
AllocObject
分配但不构造对象。我怀疑如果你在一个未构造的物体上调用它,SetLongField
可能会猛烈呕吐,就像你在这里所做的那样。请改用NewObject
;首先,您必须查询无参数构造函数的方法 ID。
您应该始终使用 CheckJNI: http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html 运行
它会告诉您您正在调用一个 JNI 函数,异常挂起,并且干净地中止。
相关文章:
- 通过JNI传递数据数组的最快方法是什么
- 为 NewObjectA() 函数创建 jvalues 的参数数组时出错 - JNI Invocation API
- 将 C# DLL 导入 C++ 以用于 JNI
- 用C++包装 Java 库 (JNI)
- 如何通过 JNI 将 C 字符串表情符号传递给 Java
- JNI从Android调用C++方法
- JVM 如何执行 JNI
- React Native (Android):无法通过 JNI 在 jobject 中返回字符串
- 如何将字符串数组返回到 java JNI
- JNI 日期值转换问题,在C++中获取不同的长整型值
- JNI,使用两个 .so 文件时出错,其中一个文件需要另一个文件
- Winapi - SetWindowLongPtr in ShutdownBlockReason创建/销毁JNI本机代码
- 将预编译的 C 共享库与 JNI/NDK 结合使用
- JNI 在应用程序中检测到错误:在为 innerclass 调用 NewObject 时使用了无效的 jobject
- 使用 jni 将返回带有模板的对象的 Java 代码转换为 c++
- 无法将DefineClass(JNI)与Qt资源一起使用
- 使用本机 JNI 静态方法实现C++ Java 运行时错误
- 从C++调用dll实现的JNI
- 如何在JNI中从线程内部调用JAVA方法
- 一般使用 java JNI GetFieldID 和 JNI