Android Studio中的JNI java.lang.NoSuchFieldError

时间:2018-07-12 21:11:10

标签: java android c++ java-native-interface

我有一个C ++库与JNI链接到Android Studio项目中的Java类,并且在env->GetFieldID()内尝试使用JNIAnalalog.cpp时遇到错误

这是我尝试从AnalogConfig.java中加载double时遇到的错误

07-12 14:30:57.597 14360-14360/com.company.myapplication A/art: art/runtime/java_vm_ext.cc:470] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.NoSuchFieldError: no "D" field "deadband" in class "[Lcom/automatak/dnp3/AnalogConfig;" or its superclasses
    art/runtime/java_vm_ext.cc:470]   at java.lang.String java.lang.Runtime.nativeLoad(java.lang.String, java.lang.ClassLoader, java.lang.String) (Runtime.java:-2)
    art/runtime/java_vm_ext.cc:470]   at java.lang.String java.lang.Runtime.doLoad(java.lang.String, java.lang.ClassLoader) (Runtime.java:1060)
    art/runtime/java_vm_ext.cc:470]   at void java.lang.Runtime.loadLibrary0(java.lang.ClassLoader, java.lang.String) (Runtime.java:975)
    art/runtime/java_vm_ext.cc:470]   at void java.lang.System.loadLibrary(java.lang.String) (System.java:1567)
    art/runtime/java_vm_ext.cc:470]   at void com.company.myapplication.MainActivity.<clinit>() (MainActivity.java:10) // This is where the c++ library is being loaded

我收到错误消息“ D”字段“死区”;但是,死区被定义为其java类内部的public double,如下所示。因此,我不确定为什么不将其视为“ D”字段。

如果我将这两行注释掉并尝试使用其他env->GetFieldID(),则会收到类似的错误:java.lang.NoSuchFieldError: no "[Lcom/automatak/dnp3/enums/EventAnalogVariation;" field "eventVariation" in class "[Lcom/automatak/dnp3/AnalogConfig;" or its superclasses

我不确定该错误是仅由JNI引起还是Android Studio是问题的一部分

此文件在我的/ app / src / main /中设置了相关文件

.
|-- cpp
|   `-- // Other libraries are located here
|
|-- dotnet
|
|-- java
|   |-- com
|   |   |-- automatak
|   |   |   `-- dnp3
|   |   |       |-- AnalogConfig.java
|   |   |       |-- EventConfig.java    
|   |   |       |-- enums
|   |   |       |   |-- EventAnalogVariation.java
|   |   |       |   `-- PointClass.java
|   |   |       |-- impl
|   |   |       `-- mock
|   |   `-- company
|   |       `-- myapplication
|   |           `-- MainActivity.java
|   |-- cpp
|   |   |-- adapters
|   |       |-- JNI.cpp
|   |       `-- JNI.h
|   |   `-- jni
|   |       |-- JNIAnalogConfig.cpp
|   |       `-- JNIAnalogConfig.h

这是文件内的所有相关代码

JNIAnalogConfig.cpp

#include "JNIAnalogConfig.h"

namespace jni
{
    namespace cache
    {
        bool AnalogConfig::init(JNIEnv* env)
        {
            auto clazzTemp = env->FindClass("[Lcom/automatak/dnp3/AnalogConfig;");
            this->clazz = (jclass) env->NewGlobalRef(clazzTemp);
            env->DeleteLocalRef(clazzTemp);

            this->deadbandField = env->GetFieldID(this->clazz, "deadband", "D");
            if(!this->deadbandField) return false; // Crashes here

            this->eventVariationField = env->GetFieldID(this->clazz, "eventVariation", "[Lcom/automatak/dnp3/enums/EventAnalogVariation;");
            if(!this->eventVariationField) return false;

            this->clazzField = env->GetFieldID(this->clazz, "clazz", "[Lcom/automatak/dnp3/enums/PointClass;");
            if(!this->clazzField) return false;

            return true;
        }
    }
}

JNIAnalog.Config.h

#ifndef OPENDNP3JAVA_JNIANALOGCONFIG_H
#define OPENDNP3JAVA_JNIANALOGCONFIG_H
#include <jni.h>
#include "../adapters/LocalRef.h"

namespace jni
{
    struct JCache;
    namespace cache
    {
        class AnalogConfig
        {
            friend struct jni::JCache;
            bool init(JNIEnv* env);
            void cleanup(JNIEnv* env);

            public:

            // field getter methods
            jdouble getdeadband(JNIEnv* env, jobject instance);
            LocalRef<jobject> geteventVariation(JNIEnv* env, jobject instance);
            LocalRef<jobject> getstaticVariation(JNIEnv* env, jobject instance);

            private:

            jclass clazz = nullptr;
            // field ids
            jfieldID deadbandField = nullptr;
            jfieldID eventVariationField = nullptr;
            jfieldID clazzField = nullptr;
        };
    }
}

#endif

AnaglogConfig.java

import com.automatak.dnp3.enums.EventAnalogVariation;
public class AnalogConfig extends EventConfig {

    public AnalogConfig(int index) {
        super(index);
    }

    public double deadband = 0;
    public EventAnalogVariation eventVariation = EventAnalogVariation.Group32Var1;
}

EventConfig.java

import com.automatak.dnp3.enums.PointClass;
public class EventConfig {

    public EventConfig(int vIndex) {
        this.vIndex = vIndex;
        this.clazz = PointClass.Class1;
    }

    public int vIndex;
    public PointClass clazz;
}

感谢您的帮助,谢谢!

0 个答案:

没有答案