注:编码工具是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对象相关推荐

  1. jvm学习笔记(3)——java对象的内存分配和对象的回收(GC)

    引言: 之前的文章已经提过,java对象实例是存放在堆上的,至于是在伊甸区.存活区还是老年区,这些都是从对象回收(GC)角度来进行的逻辑划分.所以我们先说对象的回收(GC),然后再依据GC的策略来说明 ...

  2. jvm学习笔记(2)——java对象的内存布局

    一.内存布局: 一个java对象在内存中可分为3个区域:对象头(Header).实例数据(Instance Data).对齐填充(Padding). 对象头(两部分): 对象自身运行时的数据.如哈希码 ...

  3. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  4. Mr.J-- jQuery学习笔记(二)--核心函数jQuery对象

    核心函数 函数列表 函数说明:jQuery()    主要用于获取HTML DOM元素并将其封装为jQuery对象 jQuery(): jQuery()函数是jQuery库的最核心函数,jQuery的 ...

  5. Java学习笔记二十六:Java多态中的引用类型转换

    Java多态中的引用类型转换 引用类型转换: 1.向上类型转换(隐式/自动类型转换),是小类型到大类型的转换: 2.向下类型转换(强制类型转换),是大类型到小类型的转换: 3.instanceof运算 ...

  6. MongoDB学习笔记二—Shell操作

    数据类型 MongoDB在保留JSON基本键/值对特性的基础上,添加了其他一些数据类型. null null用于表示空值或者不存在的字段:{"x":null} 布尔型 布尔类型有两 ...

  7. JavaScript学习笔记2——JavaScript操作BOM对象

    BOM模型 BOM:浏览器对象模型(Browser Object Model) BOM提供了独立于内容的.可以与浏览器窗口进行互动的对象结构 BOM可实现功能 弹出新的浏览器窗口 移动.关闭浏览器窗口 ...

  8. Java基础学习笔记(二)_Java核心技术(进阶)

    本篇文章的学习资源来自Java学习视频教程:Java核心技术(进阶)_华东师范大学_中国大学MOOC(慕课) 本篇文章的学习笔记即是对Java核心技术课程的总结,也是对自己学习的总结 文章目录 Jav ...

  9. Java学习笔记二:数据类型

    Java学习笔记二:数据类型 1. 整型:没有小数部分,允许为负数,Java整型分4种:int short long byte 1.1 Int最为常用,一个Int类型变量在内存中占用4个字节,取值范围 ...

最新文章

  1. 授权服务框架Spring Authorization Server的过滤器链
  2. jwt token 附加用户信息_SpringBoot+JWT实现token验证并将用户信息存储到@注解内
  3. Pet Shop4解密配置文件
  4. 以某个字符开始_小白从零开始数据分析01—Excel常用公式汇总(数据清洗)
  5. ZT:利用Google搜索功能来突破封锁下载
  6. raspberry pi_使用Raspberry Pi和pi-hole阻止网络上的广告
  7. 惠而浦扫地机器人充不进电_【新品上市】格卡诺新款智能扫地机器人(GKNSDJ2带刷款)...
  8. clickjacking:X-frame-options header missing 漏洞解决办法
  9. python selenium实现百度搜索
  10. 英语总结系列(二十四):历经GCT的一月
  11. 4.6 GoogLeNet CNN、tensorflow实现——python实战
  12. 用AVX2指令集优化浮点数组求和
  13. 蔡维德:Libra如果脱钩美元 美国第二天就让它下市
  14. vsd/jpg/emf/fig 转 eps
  15. 计算机文化基础形考作业,(精华版)国家开放大学电大专科《计算机文化基础》网络课形考任务6作业及答案(2页)-原创力文档...
  16. 2023程序员今年的一些现状
  17. 视频教程-其实你还不懂Word-Office/WPS
  18. HTTPSQS 1.7 版本更新内容
  19. Mac VsCode下载与安装
  20. u盘能不能给联想服务器做系统盘,联想服务器从u盘启动

热门文章

  1. 三维GIS和数字孪生的融合实现了哪些应用?
  2. 从零学Java(8)之变量,小AD竟学会了赏金计算
  3. 一、在linux下安装jenkins
  4. StatCounter
  5. 清除浮动的五种方法及优缺点
  6. 观点 | 我国人工智能人才仅5万人,专家建议培养要“从娃娃抓起”
  7. fl2440 开发板环境配置(仅供个人参考,记忆力不好)
  8. Python/numpy之ravel()多维数据展平函数
  9. PARTsolutions助力德国最著名的高档汽车制造商戴姆勒集团
  10. 容易保:这些保险常识你都了解吗?