注:编码工具是Android Studio。
目录
Native打印Java传入的String
Native接收Java传入的基本类型数组打印并修改
Native遍历打印Java传入的引用类型数组
Native通过jclass创建Java类的对象
局部引用和全局引用
用全局引用解决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"); } @Override protected 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#include #include // 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 string LOGE("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 JavaNative接收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"); } @Override protected 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#include #include // 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)); } 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] = 40Native遍历打印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"); } @Override protected 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#include #include // 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 (env->GetObjectArrayElement(arr, i));// 根据下标获取每一个对象元素 const char *str = env->GetStringUTFChars(jstr, NULL);// 将jstring对象转换为native string LOGE("%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: eNative通过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"); } @Override protected 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#include #include // 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类构造函数的MethodID jmethodID pJConMethodID = env->GetMethodID(pJclass, " ", "()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"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_jni); } private native void referenceTest(); public void click(View view) { referenceTest(); } }
Native代码
#include#include #include // 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函数创建的引用都是局部引用,函数执行完自动释放内存空间 // 由此可能引发crash if(!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用全局引用解决crash问题>&, 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 >&, 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 >&, 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 >&, 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 >&, 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 (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) ...
JniActivity代码不变。
Native代码
#include#include #include // 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 (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"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_jni); } private native void testExtern(); public void click(View view) { testExtern(); } }
Native代码一
#include#include #include // 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#include #include // 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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)