java - 调用 Android Java JNI GetDoubleField() 时发出 SIGABORT
问题描述
调用 GetDoubleField() 时,我得到一个 SIGABORT。
我写了一个小示例程序来显示这个问题......
MainActivity.java
package net.directionalsystems.jnitest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private static final String TAG = "Mainactivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
JniComms jc = new JniComms();
jc.latitude = 10;
jc.logitude = 20;
jc.txtLocation = "Hello";
try {
tv.setText(stringFromJNI(jc));
}
catch (Exception e)
{
Log.e(TAG, "onCreate: ", e);
}
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(JniComms jc);
}
JniComms.java
package net.directionalsystems.jnitest;
import java.util.ArrayList;
public class JniComms
{
public double latitude;
public double logitude;
public String txtLocation;
//public ArrayList<BleStatus> bleStatusArray;
}
本机 lib.cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_net_directionalsystems_jnitest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jo,
jobject jc)
{
jclass jcClass = env->GetObjectClass(jc);
jfieldID iId = env->GetFieldID(jcClass, "latitude", "D");
// Executing the next line causes SIGABORT
jdouble latitude = env->GetDoubleField(jcClass, iId);
std::string hello = "Hello world";
return env->NewStringUTF(hello.c_str());
}
build.gradle 文件如下...
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "net.directionalsystems.jnitest"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
customDebugType {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
debuggable true
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
这一定是我正在做的简单而愚蠢的事情。
我想调试 NDK 代码,但我得到的只是显示的 jni.h 文件,无法进入 JNI 代码本身。拥有这种能力可能会让我知道哪里出了问题。
非常感谢您的帮助。
最好的问候,杰基
解决方案
读取实例(非静态)字段时,您应该传递对象,而不是类。
所以替换:
jdouble latitude = env->GetDoubleField(jcClass, iId);
和:
jdouble latitude = env->GetDoubleField(jc, iId);
推荐阅读
- axon - QuartzDeadlineManager (Scheduler) 无意中替换了配置的 TransactionManager
- c# - 用对象 C# 中的值替换存储在文件中的值
- python - 在python中打印特殊字符%,周围没有额外的''
- laravel - Laravel/Vue:在 Vue 入口点包装布局,但不能在“内容”部分使用
- python - Generating approximately unique set of numbers from numpy array
- ios - Swift 致命错误:索引超出范围(超出范围索引)
- python - 重新运行时Airflow是否缓存全局变量
- rust - 为什么我的发布模式 Rust 可执行文件包含具有绝对路径名的字符串?
- r - 如图所示创建条形图
- game-engine - Game Maker Studio 2 数组取错误值