JNI学习笔记——(二)Native操作Java对象
注:编码工具是Android Studio。
目录
Native打印Java传入的String
Native接收Java传入的基本类型数组打印并修改
Native遍历打印Java传入的引用类型数组
Native通过jclass创建Java类的对象
局部引用和全局引用
定义在函数外面的引用造成的crash
用全局引用解决crash问题
extern 声明变量和函数
Native打印Java传入的String
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;import com.android.jni.study.R;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private native void deliveryStringToNative(String str);public void click(View view) {deliveryStringToNative("Hello From Java");}
}
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_deliveryStringToNative(JNIEnv *env,jobject thiz, jstring jstr) {const char *str = env->GetStringUTFChars(jstr, 0);// 将jstring转换为Native stringLOGE("str = %s", str);// LOGE调用格式类似于C的printf
}
Activity运行界面,后面案例界面都一样,不贴了。
点击click输出
2021-12-16 21:57:18.104 23293-23293/com.wcc.jni.study E/NATIVE: str = Hello From Java
Native接收Java传入的基本类型数组打印并修改
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.view.View;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private int[] intArr = {1, 2, 3, 4};private native void deliveryIntArrToNative(int[] arr);public void click(View view) {deliveryIntArrToNative(intArr);for (int i = 0; i < intArr.length; i ++) {Log.e("Java", "intArr[" + i + "] = " + intArr[i]);}}
}
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_deliveryIntArrToNative(JNIEnv *env, jobject thiz,jintArray arr) {jint *intArr = env->GetIntArrayElements(arr, NULL);// 将Java传到Native的数组转换为Native数组jsize arrayLength = env->GetArrayLength(arr);// 获取Java传到Native数组的长度int i;for(i = 0; i < arrayLength; i ++){int tmp = *(intArr + i);// 修改结果不会同步到Java*(intArr + i) = tmp * 10;LOGE("native before intArr[%d] = %d, after intArr[%d] = %d", i, tmp, i, *(intArr + i));}/*** 第三个参数取值* 0:刷新Java数组,释放Native数组* JNI_COMMIT:只刷新Java数组,不释放Native数组* JNI_ABORT:只是放Native数组,不刷新Java数组*/env->ReleaseIntArrayElements(arr, intArr, 0);// 将Native修改同步到Java
}
点击click输出
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/NATIVE: native before intArr[0] = 1, after intArr[0] = 10
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/NATIVE: native before intArr[1] = 2, after intArr[1] = 20
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/NATIVE: native before intArr[2] = 3, after intArr[2] = 30
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/NATIVE: native before intArr[3] = 4, after intArr[3] = 40
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/Java: intArr[0] = 10
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/Java: intArr[1] = 20
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/Java: intArr[2] = 30
2021-12-16 22:11:57.256 23395-23395/com.wcc.jni.study E/Java: intArr[3] = 40
Native遍历打印Java传入的引用类型数组
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private String[] strArr = {"a", "b", "c", "d", "e"};private native void deliveryStringArrToNative(String[] arr);public void click(View view) {deliveryStringArrToNative(strArr);}
}
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_deliveryStringArrToNative(JNIEnv *env, jobject thiz,jobjectArray arr) {jsize arrayLength = env->GetArrayLength(arr);// 获取Java传到Native数组的长度int i;for(i = 0; i < arrayLength; i ++){jstring jstr = static_cast<jstring>(env->GetObjectArrayElement(arr, i));// 根据下标获取每一个对象元素const char *str = env->GetStringUTFChars(jstr, NULL);// 将jstring对象转换为native stringLOGE("%s", str);}
}
点击click输出
2021-12-16 22:21:50.487 23504-23504/com.wcc.jni.study E/NATIVE: a
2021-12-16 22:21:50.487 23504-23504/com.wcc.jni.study E/NATIVE: b
2021-12-16 22:21:50.487 23504-23504/com.wcc.jni.study E/NATIVE: c
2021-12-16 22:21:50.487 23504-23504/com.wcc.jni.study E/NATIVE: d
2021-12-16 22:21:50.487 23504-23504/com.wcc.jni.study E/NATIVE: e
Native通过jclass创建Java类的对象
Person类代码
package com.android.jni.study;import android.util.Log;public class Person {private String name;public Person(){Log.e("NATIVE", "Person构造函数被调用了");}public String getName() {return name;}public void setName(String name) {this.name = name;}public void print() {Log.e("NATIVE", "Person{" +"name='" + name + '\'' +'}');}
}
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private static native void nativeOperateJavaClass(Person person);public void click(View view) {nativeOperateJavaClass(new Person());}
}
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_nativeOperateJavaClass(JNIEnv *env,jclass clazz, jobject person) {// 获取Java Person类的jclass 方式一jclass pJclass = env->GetObjectClass(person);// 获取Java Person类的jclass 方式二jclass pJclass2 = env->FindClass("com/android/jni/study/Person");// 创建Person对象 方式一, 这种方式不会调用Person类的构造函数LOGE("AllocObject不会调用构造函数");jobject pJobject = env->AllocObject(pJclass);// 创建Person对象 方式二// 先获取Person类构造函数的MethodIDjmethodID pJConMethodID = env->GetMethodID(pJclass, "<init>", "()V");LOGE("NewObject会调用构造函数");jobject pJobject2 = env->NewObject(pJclass2, pJConMethodID);// 获取name的FieldID,赋值jfieldID nameId = env->GetFieldID(pJclass, "name", "Ljava/lang/String;");jstring pJstring = env->NewStringUTF("HtFieldID(pJclass2, appy");env->SetObjectField(pJobject, nameId, pJstring);// 获取setName的MethodID,并调用jmethodID setNameId = env->GetMethodID(pJclass, "setName", "(Ljava/lang/String;)V");jstring name2 = env->NewStringUTF("Object2");env->CallVoidMethod(pJobject2, setNameId, name2);// 调用pJobject和pJobject2的print方法查看结果jmethodID printId = env->GetMethodID(pJclass, "print", "()V");env->CallVoidMethod(pJobject, printId);env->CallVoidMethod(pJobject2, printId);
}
点击click输出
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: Person构造函数被调用了
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: AllocObject不会调用构造函数
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: NewObject会调用构造函数
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: Person构造函数被调用了
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: Person{name='HtFieldID(pJclass2, appy'}
2021-12-16 22:42:17.295 23706-23706/com.wcc.jni.study E/NATIVE: Person{name='Object2'}
局部引用和全局引用
定义在函数外面的引用造成的crash
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private native void referenceTest();public void click(View view) {referenceTest();}
}
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定jclass jclz = nullptr;
extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_referenceTest(JNIEnv *env, jobject thiz) {// 没有用env->NewGlobalRef函数创建的引用都是局部引用,函数执行完自动释放内存空间// 由此可能引发crashif(!jclz){jclz = env->FindClass("com/android/jni/study/Person");}env->AllocObject(jclz);
}
第二次点击click导致crash,jclz定义在函数外,函数执行完自动释放内存空间,但是jclz并没有置为nullptr,所以第二次进函数不会走if语句体,导致crash。
输出
2021-12-16 22:52:55.817 1937-2780/system_process E/TaskPersister: File error accessing recents directory (directory doesn't exist?).
2021-12-16 22:52:56.996 23958-23958/com.wcc.jni.study E/m.wcc.jni.stud: JNI ERROR (app bug): accessed stale Local 0x69 (index 6 in a table of size 6)
2021-12-16 22:52:56.997 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x69
2021-12-16 22:52:56.997 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: java_vm_ext.cc:570] from void com.android.jni.study.JniActivity.referenceTest()
2021-12-16 22:52:57.123 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] Runtime aborting...
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] Dumping all threads without mutator lock held
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] All threads:
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] DALVIK THREADS (14):
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] "main" prio=10 tid=1 Runnable
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | group="" sCount=0 dsCount=0 flags=0 obj=0x72c261f0 self=0xed137800
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | sysTid=23958 nice=-10 cgrp=default sched=0/0 handle=0xed732dc8
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | state=R schedstat=( 354717885 49362006 326 ) utm=13 stm=22 core=2 HZ=100
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | stack=0xff162000-0xff164000 stackSize=8192KB
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | held mutexes= "abort lock" "mutator lock"(shared held)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #00 pc 00493b03 /apex/com.android.runtime/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+115)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #01 pc 005b1f62 /apex/com.android.runtime/lib/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+994)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #02 pc 005acdf1 /apex/com.android.runtime/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+65)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #03 pc 005d2c61 /apex/com.android.runtime/lib/libart.so (art::DumpCheckpoint::Run(art::Thread*)+929)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #04 pc 005cab96 /apex/com.android.runtime/lib/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+486)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #05 pc 005c9dfc /apex/com.android.runtime/lib/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+2268)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #06 pc 00579680 /apex/com.android.runtime/lib/libart.so (art::AbortState::DumpAllThreads(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, art::Thread*) const+448)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #07 pc 00564ce0 /apex/com.android.runtime/lib/libart.so (art::Runtime::Abort(char const*)+1536)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #08 pc 000249b3 /apex/com.android.runtime/lib/libartbase.so (_ZNSt3__110__function6__funcIPFvPKcENS_9allocatorIS5_EES4_EclEOS3_+35)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #09 pc 0000bac7 /system/lib/libbase.so (android::base::LogMessage::~LogMessage()+727)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #10 pc 003e539d /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1725)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #11 pc 003e5658 /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbortF(char const*, char const*, ...)+120)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #12 pc 005b8ee4 /apex/com.android.runtime/lib/libart.so (art::Thread::DecodeJObject(_jobject*) const+836)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #13 pc 003d601d /apex/com.android.runtime/lib/libart.so (art::(anonymous namespace)::ScopedCheck::CheckInstance(art::ScopedObjectAccess&, art::(anonymous namespace)::ScopedCheck::InstanceKind, _jobject*, bool)+157)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #14 pc 003d5248 /apex/com.android.runtime/lib/libart.so (art::(anonymous namespace)::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&, char, art::(anonymous namespace)::JniValueType)+456)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #15 pc 003d4729 /apex/com.android.runtime/lib/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*)+745)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #16 pc 003c1ea6 /apex/com.android.runtime/lib/libart.so (art::(anonymous namespace)::CheckJNI::AllocObject(_JNIEnv*, _jclass*)+886)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #17 pc 0000126b /data/app/com.wcc.jni.study-TwgNPWT7xauOdeBeX_jYPw==/base.apk!libnative-lib.so (offset 4000) (_JNIEnv::AllocObject(_jclass*)+59)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #18 pc 000011d3 /data/app/com.wcc.jni.study-TwgNPWT7xauOdeBeX_jYPw==/base.apk!libnative-lib.so (offset 4000) (Java_com_android_jni_study_JniActivity_referenceTest+115)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #19 pc 00144f67 /apex/com.android.runtime/lib/libart.so (art_quick_generic_jni_trampoline+71)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #20 pc 0013e7d2 /apex/com.android.runtime/lib/libart.so (art_quick_invoke_stub+338)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #21 pc 00149a69 /apex/com.android.runtime/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+281)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #22 pc 00332502 /apex/com.android.runtime/lib/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+386)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #23 pc 0032c19c /apex/com.android.runtime/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+988)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #24 pc 0068433c /apex/com.android.runtime/lib/libart.so (MterpInvokeDirect+700)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #25 pc 00138921 /apex/com.android.runtime/lib/libart.so (mterp_op_invoke_direct+33)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #26 pc 00027c7c [anon:dalvik-classes2.dex extracted in memory from /data/app/com.wcc.jni.study-TwgNPWT7xauOdeBeX_jYPw==/base.apk!classes2.dex] (com.android.jni.study.JniActivity.click)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #27 pc 002f8e0a /apex/com.android.runtime/lib/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.6689468213397061768+298)
2021-12-16 22:52:57.124 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #28 pc 002ffcc5 /apex/com.android.runtime/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+181)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #29 pc 0066fbd9 /apex/com.android.runtime/lib/libart.so (artQuickToInterpreterBridge+1209)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #30 pc 0014503d /apex/com.android.runtime/lib/libart.so (art_quick_to_interpreter_bridge+77)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #31 pc 0013e7d2 /apex/com.android.runtime/lib/libart.so (art_quick_invoke_stub+338)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #32 pc 00149a69 /apex/com.android.runtime/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+281)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #33 pc 0055a513 /apex/com.android.runtime/lib/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+99)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #34 pc 0055c32f /apex/com.android.runtime/lib/libart.so (art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned int)+1327)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #35 pc 004c9153 /apex/com.android.runtime/lib/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)+83)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at com.android.jni.study.JniActivity.referenceTest(Native method)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at com.android.jni.study.JniActivity.click(JniActivity.java:40)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at java.lang.reflect.Method.invoke(Native method)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.view.View.performClick(View.java:7140)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.view.View.performClickInternal(View.java:7117)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.view.View.access$3500(View.java:801)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.view.View$PerformClick.run(View.java:27351)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.os.Handler.handleCallback(Handler.java:883)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.os.Handler.dispatchMessage(Handler.java:100)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.os.Looper.loop(Looper.java:214)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at android.app.ActivityThread.main(ActivityThread.java:7356)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at java.lang.reflect.Method.invoke(Native method)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630]
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] "Jit thread pool worker thread 0" prio=10 tid=2 Native
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | group="" sCount=1 dsCount=0 flags=1 obj=0x14940220 self=0xd9d00000
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | sysTid=23959 nice=0 cgrp=default sched=0/0 handle=0xd9c04d90
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | state=S schedstat=( 4499646 5710051 28 ) utm=0 stm=0 core=2 HZ=100
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | stack=0xd9b06000-0xd9b08000 stackSize=1023KB
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] | held mutexes=
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] kernel: (couldn't read /proc/self/task/23959/stack)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #00 pc 00000ad7 [vdso] (__kernel_vsyscall+7)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #01 pc 00092328 /apex/com.android.runtime/lib/bionic/libc.so (syscall+40)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #02 pc 00150802 /apex/com.android.runtime/lib/libart.so (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+114)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #03 pc 00150783 /apex/com.android.runtime/lib/libart.so (art::ConditionVariable::Wait(art::Thread*)+35)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #04 pc 005d4aa5 /apex/com.android.runtime/lib/libart.so (art::ThreadPool::GetTask(art::Thread*)+261)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #05 pc 005d3c05 /apex/com.android.runtime/lib/libart.so (art::ThreadPoolWorker::Run()+133)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #06 pc 005d369f /apex/com.android.runtime/lib/libart.so (art::ThreadPoolWorker::Callback(void*)+239)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #07 pc 0011a8e5 /apex/com.android.runtime/lib/bionic/libc.so (__pthread_start(void*)+53)
2021-12-16 22:52:57.125 23958-23958/com.wcc.jni.study A/m.wcc.jni.stud: runtime.cc:630] native: #08 pc 000af6a7 /apex/com.android.runtime/lib/bionic/libc.so (__start_thread+71)
...
用全局引用解决crash问题
JniActivity代码不变。
Native代码
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定jclass jclz = nullptr;
extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_referenceTest(JNIEnv *env, jobject thiz) {if(!jclz){jclz = env->FindClass("com/android/jni/study/Person");jclz = static_cast<jclass>(env->NewGlobalRef(jclz));}env->AllocObject(jclz);
}
此时多次点击click不会导致crash。
全局引用函数执行完不会自动释放内存空间,需要在不需要使用时,手动调用env->DeleteGlobalRef函数释放内存空间。
extern 声明变量和函数
可以在一个文件中声明变量和函数,在另一个文件中为变量赋值、实现函数,在声明的文件中可以使用变量和函数。
JniActivity代码
package com.android.jni.study;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;public class JniActivity extends AppCompatActivity {// 加载本地库static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jni);}private native void testExtern();public void click(View view) {testExtern();}
}
Native代码一
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定extern int age;
extern void printAge(int age);extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_testExtern(JNIEnv *env, jobject thiz) {printAge(age);
}
Native代码二
#include <jni.h>
#include <string>
#include <android/log.h> // Native层打印log,类似Android Java的log#define TAG "NATIVE" // 定义Tag宏
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) // 定义LOGE宏函数,格式固定
int age = 99;
void printAge(int age) {LOGE("age = %d", age);
}
点击click输出
2021-12-16 23:09:07.075 24327-24327/com.wcc.jni.study E/NATIVE: age = 99
JNI学习笔记——(二)Native操作Java对象相关推荐
- jvm学习笔记(3)——java对象的内存分配和对象的回收(GC)
引言: 之前的文章已经提过,java对象实例是存放在堆上的,至于是在伊甸区.存活区还是老年区,这些都是从对象回收(GC)角度来进行的逻辑划分.所以我们先说对象的回收(GC),然后再依据GC的策略来说明 ...
- jvm学习笔记(2)——java对象的内存布局
一.内存布局: 一个java对象在内存中可分为3个区域:对象头(Header).实例数据(Instance Data).对齐填充(Padding). 对象头(两部分): 对象自身运行时的数据.如哈希码 ...
- Java学习笔记二十五:Java面向对象的三大特性之多态
Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...
- Mr.J-- jQuery学习笔记(二)--核心函数jQuery对象
核心函数 函数列表 函数说明:jQuery() 主要用于获取HTML DOM元素并将其封装为jQuery对象 jQuery(): jQuery()函数是jQuery库的最核心函数,jQuery的 ...
- Java学习笔记二十六:Java多态中的引用类型转换
Java多态中的引用类型转换 引用类型转换: 1.向上类型转换(隐式/自动类型转换),是小类型到大类型的转换: 2.向下类型转换(强制类型转换),是大类型到小类型的转换: 3.instanceof运算 ...
- MongoDB学习笔记二—Shell操作
数据类型 MongoDB在保留JSON基本键/值对特性的基础上,添加了其他一些数据类型. null null用于表示空值或者不存在的字段:{"x":null} 布尔型 布尔类型有两 ...
- JavaScript学习笔记2——JavaScript操作BOM对象
BOM模型 BOM:浏览器对象模型(Browser Object Model) BOM提供了独立于内容的.可以与浏览器窗口进行互动的对象结构 BOM可实现功能 弹出新的浏览器窗口 移动.关闭浏览器窗口 ...
- Java基础学习笔记(二)_Java核心技术(进阶)
本篇文章的学习资源来自Java学习视频教程:Java核心技术(进阶)_华东师范大学_中国大学MOOC(慕课) 本篇文章的学习笔记即是对Java核心技术课程的总结,也是对自己学习的总结 文章目录 Jav ...
- Java学习笔记二:数据类型
Java学习笔记二:数据类型 1. 整型:没有小数部分,允许为负数,Java整型分4种:int short long byte 1.1 Int最为常用,一个Int类型变量在内存中占用4个字节,取值范围 ...
最新文章
- 授权服务框架Spring Authorization Server的过滤器链
- jwt token 附加用户信息_SpringBoot+JWT实现token验证并将用户信息存储到@注解内
- Pet Shop4解密配置文件
- 以某个字符开始_小白从零开始数据分析01—Excel常用公式汇总(数据清洗)
- ZT:利用Google搜索功能来突破封锁下载
- raspberry pi_使用Raspberry Pi和pi-hole阻止网络上的广告
- 惠而浦扫地机器人充不进电_【新品上市】格卡诺新款智能扫地机器人(GKNSDJ2带刷款)...
- clickjacking:X-frame-options header missing 漏洞解决办法
- python selenium实现百度搜索
- 英语总结系列(二十四):历经GCT的一月
- 4.6 GoogLeNet CNN、tensorflow实现——python实战
- 用AVX2指令集优化浮点数组求和
- 蔡维德:Libra如果脱钩美元 美国第二天就让它下市
- vsd/jpg/emf/fig 转 eps
- 计算机文化基础形考作业,(精华版)国家开放大学电大专科《计算机文化基础》网络课形考任务6作业及答案(2页)-原创力文档...
- 2023程序员今年的一些现状
- 视频教程-其实你还不懂Word-Office/WPS
- HTTPSQS 1.7 版本更新内容
- Mac VsCode下载与安装
- u盘能不能给联想服务器做系统盘,联想服务器从u盘启动