我有一个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;
}
感谢您的帮助,谢谢!