在Android 4.4及更早版本上,GetFieldID失败 [英] GetFieldID fails on Android 4.4 and older

查看:107
本文介绍了在Android 4.4及更早版本上,GetFieldID失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用dlib库进行人脸检测,但是在旧手机上不起作用.

I'd like to use a dlib library for face detection, but it doesn't work on old phones.

我崩溃并显示以下堆栈跟踪信息:

I crashes with the following stack trace:

E/AndroidRuntime( 4288): FATAL EXCEPTION: pool-1-thread-1
E/AndroidRuntime( 4288): java.lang.ExceptionInInitializerError
E/AndroidRuntime( 4288):    at com.tzutalin.dlibtest.MainActivity.runDetectAsync(MainActivity.java:235)
E/AndroidRuntime( 4288):    at com.tzutalin.dlibtest.MainActivity_.access$301(MainActivity_.java:34)
E/AndroidRuntime( 4288):    at com.tzutalin.dlibtest.MainActivity_$6.execute(MainActivity_.java:158)
E/AndroidRuntime( 4288):    at org.androidannotations.api.BackgroundExecutor$Task.run(BackgroundExecutor.java:405)
E/AndroidRuntime( 4288):    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
E/AndroidRuntime( 4288):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
E/AndroidRuntime( 4288):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
E/AndroidRuntime( 4288):    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:150)
E/AndroidRuntime( 4288):    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:264)
E/AndroidRuntime( 4288):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
E/AndroidRuntime( 4288):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
E/AndroidRuntime( 4288):    at java.lang.Thread.run(Thread.java:856)
E/AndroidRuntime( 4288): Caused by: java.lang.NoSuchFieldError: no field with name='mLabel' signature='java/lang/String' in class Lcom/tzutalin/dlib/VisionDetRet;
E/AndroidRuntime( 4288):    at com.tzutalin.dlib.PeopleDet.jniNativeClassInit(Native Method)
E/AndroidRuntime( 4288):    at com.tzutalin.dlib.PeopleDet.<clinit>(PeopleDet.java:42)
E/AndroidRuntime( 4288):    ... 12 more

因此,C代码如下所示:

So, the C code looks like this:

void JNIEXPORT DLIB_JNI_METHOD(jniNativeClassInit)(JNIEnv* env, jclass _this) {
  jclass detRetClass = env->FindClass("com/tzutalin/dlib/VisionDetRet");
  CHECK_NOTNULL(detRetClass);
  gVisionDetRetOffsets.label =
      env->GetFieldID(detRetClass, "mLabel", "java/lang/String");
  gVisionDetRetOffsets.confidence =
      env->GetFieldID(detRetClass, "mConfidence", "F");
  gVisionDetRetOffsets.left = env->GetFieldID(detRetClass, "mLeft", "I");
  gVisionDetRetOffsets.top = env->GetFieldID(detRetClass, "mTop", "I");
  gVisionDetRetOffsets.right = env->GetFieldID(detRetClass, "mRight", "I");
  gVisionDetRetOffsets.bottom = env->GetFieldID(detRetClass, "mBottom", "I");
  gVisionDetRetOffsets.addLandmark =
      env->GetMethodID(detRetClass, "addLandmark", "(II)Z");
  if (gVisionDetRetOffsets.addLandmark == NULL) {
    LOG(FATAL) << "Can't Find Method addLandmark(int,int)";
  }
  LOG(INFO) << "JniNativeClassIni Success";
}

以及相关的Java类:

And the related Java class:

public final class VisionDetRet {
    private String mLabel;
    private float mConfidence;
    private int mLeft;
    private int mTop;
    private int mRight;
    private int mBottom;
    private ArrayList<Point> mLandmarkPoints = new ArrayList<>();

    VisionDetRet() {
    }

    // Other code
}

因此,字段显然在这里,并且它得到了类(CHECK_NOTNULL(detRetClass)成功).那么,为什么它在旧手机上崩溃? Google并没有提供太多帮助,而且我对NDK/JNI知识还很陌生.

So, the fields are obviously here, and it gets the class (CHECK_NOTNULL(detRetClass) succeeds). So why is it crashing on older phones? Google didn't helped much, and I'm pretty new to NDK/JNI stuff.

P. S. Java文件是此处,C文件为这里(是的,它们位于2个不同的存储库中)

P. S. The Java file is here and the C file is here (yup, they are in 2 different repos)

推荐答案

我不确定这在任何Android版本上如何工作,因为java/lang/StringGetFieldID的不正确签名.

I'm not sure how this has worked for you on any Android version, because java/lang/String is an incorrect signature for GetFieldID.

对于类,签名应为L fully-qualified-class ;,因此在您的情况下,您需要Ljava/lang/String;

For classes, the signature should be L fully-qualified-class ;, so in your case you'd want Ljava/lang/String;

这篇关于在Android 4.4及更早版本上,GetFieldID失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆