Android Ошибка JNI: NoSuchMethodError: нет не-статического c метода - PullRequest
1 голос
/ 04 марта 2020

То, что я пытаюсь сделать, упрощено ниже.

  1. Java -> Вызов функции C ++ A
  2. Функция C ++ A вызывает функцию C ++ B
  3. C ++ функция B вызывает Java метод C

Мне нужно хранить JVM (2) и глобальный jobject (3).

Но в части 3,

JNI DETECTED ERROR IN APPLICATION: JNI CallVoidMethodV called with pending exception java.lang.NoSuchMethodError: no non-static method "Lpackage/name/here/d/b;.setInput([F)V"

Я всегда получал эту ошибку.


Код

Структура

  • Оболочка. java
  • native -lib. cpp
  • Wrapper. cpp

** <-> означает связь

Другое Java Классы <-> Wrapper. java

Wrapper. java <-> native-lib. cpp

native-lib. cpp <-> Wrapper. cpp

Wrapper. cpp <-> Другие классы C ++


Wrapper. java

private static long wrapperAddr = 0; // initializes later

private tfModel model;
private native void nativeSetModel(long native_ptr, tfModel model);

public Wrapper(...){
    ...

    model = tfModel.create(tfModel.Model.MNIST, tfModel.Device.CPU, 1);
    nativeSetModel(wrapperAddr, model);
}

native-lib. cpp

extern "C" JNIEXPORT void JNICALL
Java_package_name_here_jni_Wrapper_nativeSetModel(JNIEnv *env,
                                                      jobject instance,
                                                      jlong native_ptr,
                                                      jobject model){

  auto wrapper = reinterpret_cast<Wrapper *>(native_ptr);

  wrapper->setModel(env, model);
}

Упаковщик. cpp

void setModel(JNIEnv *env, jobject _model){
    env->GetJavaVM(&translater::jvm);    
    jobject gmodel = env->NewGlobalRef(_model);    
    translater::model = gmodel;
  }

функция A

...
translater::setInputTS(input1, 100);  // error starts here

...

translater.h / translater. cpp ( функция B )

class translater{
public:

    inline static JavaVM *jvm = nullptr;
    inline static jobject model = nullptr;

    // from: https://stackoverflow.com/a/30026231/8176989
    static bool GetJniEnv(JavaVM *vm, JNIEnv **env);  

    static void predictTS(std::vector<float> &output);

    static void translater::setInputTS(float* input, int len) {


    JNIEnv *env;
    bool did_attach = GetJniEnv(jvm, &env);

    if(did_attach){


        jclass clazz = env->GetObjectClass(model);
        jmethodID jid_input = env->GetMethodID(clazz, "setInput", "([F)V");  // Here is where error happens

    }

    ...    
};

tfModel. java

public abstract class tfModel{
...

    public void setInput(float[] array){
        if(inputIndex < inputImageNum)
            setInput_Image(inputIndex, array);
        else
            setInput_Tensor(inputIndex - inputImageNum, array);

        ++inputIndex;
    }

}

Как n Я правильно звоню jmethodID jid_input = env->GetMethodID(clazz, "setInput", "([F)V");?

1 Ответ

0 голосов
/ 04 марта 2020

Это было из-за глупой оптимизации компилятора. Я добавил настройки Proguard, и все работает отлично.

https://developer.android.com/studio/build/shrink-code#keep -код

.pro файл

...
// added
-keep abstract class package.name.here.module.tfModel{
    *;
}
...