注:编码工具是Android Studio。
目录
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 <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 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 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");
}
@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 <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");
}
@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 <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 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: 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");
}
@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 <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类构造函数的MethodID
jmethodID 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");
}
@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 <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函数创建的引用都是局部引用,函数执行完自动释放内存空间
// 由此可能引发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<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");
}
@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 <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