JNI学习笔记——(二)Native *** 作Java对象

JNI学习笔记——(二)Native *** 作Java对象,第1张

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");
    }

    @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 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 
#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] = 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 
#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: 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 
#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>&, 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)
...
用全局引用解决crash问题

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/5671868.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存