首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通常使用java JNI、GetFieldID和JNI。

通常使用java JNI、GetFieldID和JNI。
EN

Stack Overflow用户
提问于 2012-04-25 10:17:00
回答 3查看 6.3K关注 0票数 0

我在JNI上的运气似乎一点也不好。我在等我买的一本书送到,但现在还在反复试验。

我正在使用JNI实现一个Lua赋值器。evaluatorNew()只是创建一个新的Evaluator()对象,按照Java端的描述创建一个新的CPtr()类对象,将我们的Evaluator()对象的指针分配给CPtr的'peer‘成员,然后返回新的CPtr jobject。

代码语言:javascript
复制
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()‘调用的内容。

代码语言:javascript
复制
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() {}

}

正如您在下面看到的,没有堆栈跟踪可言。

代码语言:javascript
复制
(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函数的转储:

代码语言:javascript
复制
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行:

代码语言:javascript
复制
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
{ return functions->GetFieldID(this, clazz, name, sig); } // 708

有什么帮助吗?如果我需要澄清什么,请告诉我。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-25 10:26:22

AllocObject分配对象,但不构造对象。我怀疑如果你在一个未构造的对象上调用SetLongField,它可能会吐得很厉害,就像你在这里所做的那样。请改用NewObject;首先必须查询无参数构造函数的方法。

票数 1
EN

Stack Overflow用户

发布于 2012-04-25 16:59:48

你的代码中有很多是理所当然的。你需要检查每一个JNI调用的结果,寻找一个异常,如果你得到一个异常,就中止。你不应该像那样堆叠Lisp风格的函数调用,并希望它们都返回可用的值。

票数 3
EN

Stack Overflow用户

发布于 2012-04-30 22:15:01

您应该始终使用CheckJNI运行:http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html

它会告诉您正在调用JNI函数,但异常挂起,并干净利落地中止了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10308512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档