Make writing a habit together! This is the fourth day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

1. The background

This article summarizes common problems and solutions in JNI development.

2. The SDK version is specified during compilation

Intelligent voice interaction SDK engineering module compilation specified ANDROID_PLATFORM unified is 23: -dandroid_platform =23, NDK uses version 17, it can run on existing devices, but it can’t run on a newly purchased TEMi mobile robot. The signal processing library reports the following problem:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__aeabi_memclr4" referenced by "/data/app/com.xxx.xxxx.robot-2/lib/arm/libkeos_signal_processing.so"...
Copy the code

At first, I thought it was because of some incompatible method used in the signal processing library, but I still reported this error after changing the implementation of the library to empty. Online, I found that the target version does not correspond to the target device, and the robot’s system version is 6.0. APP_PLATFORM = android-26; APP_PLATFORM = android-26;

Github.com/android/ndk…

Github.com/android/ndk…

The problem is explained on the official website:

These errors are shown in the log when attempting to load the native library. This symbol can be any of __aeabi_*; Of these, __aeabi_memcpy and __aeabi_memclr are probably the most common. This problem is documented in problem 126

2. Using _FILE_OFFSET_BITS=64 with older API levels

Similar to the last one, this is an API version issue.

Before unifying header files, the NDK did not support _FILE_OFFSET_BITS=64. If this option is defined when building the application, it is silently ignored. Now, the _FILE_OFFSET_BITS=64 option is supported by a unified header file, but in older versions of Android, there are few off_t apis available as off64_t variants. Therefore, if this feature is used with the older API level, there will be fewer functions available.

This problem is explained in detail in the R16 blog post and bionic documentation.

Problem: API not present in minSdkVersion obtained by build request.

Solution: Disable _FILE_OFFSET_BITS=64 or improve minSdkVersion.

3. jni local reference table overflow (max=512)

Under normal circumstances, the local reference applied in the method will be automatically released after the method is executed, so we have not paid much attention to the release of the local reference. As a result, two JStrings in the Looper method of a thread have been used up and not released, resulting in the leak crash after several rounds of interaction.

4. FindClassCan’t find the class

Types of common problems:

  1. Make sure that the class name string is properly formatted and that the JNI class name begins with the package name and is delimited with a slash, for examplejava/lang/String. If you want to find an array class, you need to start with the appropriate number of English square brackets, and you must also use “L” and “;” Wrap the class, soStringThe one-dimensional array of will be[Ljava/lang/String;. If you’re looking for inner classes, use “$” instead of”.” Can be used in.class filesjavapIs to find the internal name of the class.
  2. If code obfuscation is enabled, make sure the class name you are looking for is not obfuscated.
  3. If the class name is in the correct form, you may be experiencing classloader problems.FindClassThe startup class search is required in the classloader associated with the code. It checks the call stack as follows:
    Foo.myfunc(Native Method)
        Foo.main(Foo.java:10)
Copy the code

The top-level method is foo.myfunc. FindClass finds the ClassLoader object associated with class Foo and uses it.

This approach generally meets our needs. However, if you are on a native thread (for example, by calling pthread_CREATE and then attaching it with AttachCurrentThread), you may have problems. Because there are no stack frames in this thread, if FindClass is called from this thread, JavaVM will start in the “system” classloader (rather than the classloader associated with the application), so attempts to find application-specific classes will fail.

You can solve this problem in the following ways:

  • inJNI_OnLoadExecute once inFindClassFind, and then cache the class reference for later use. In the implementationJNI_OnLoadAny of the processes issuedFindClassAll calls are used and calledSystem.loadLibraryClass loaders associated with the function of. (This is a special rule to make library initialization easier.) If our application code is going to load the library,FindClassThe correct class loader will be used.
  • Get the Class parameter by declaring a native method and passing it inFoo.classTo pass an instance of the class to the function that needs it.
  • Cache in a convenient locationClassLoaderObject, and then emitted directlyloadClassCall, this is a bit more cumbersome, and caching the Classloader may also have some problems.
  • usejava/lang/ClassLoaderthegetClassLoaderAnd then callfindClass:
static jobject gClassLoader; static jmethodID gFindClassMethod; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) { gJvm = pjvm; // cache the JavaVM pointer auto env = getEnv(); //replace with one of your classes in the line below auto randomClass = env->FindClass("com/example/RandomClass"); jclass classClass = env->GetObjectClass(randomClass); auto classLoaderClass = env->FindClass("java/lang/ClassLoader"); auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;" ); gClassLoader = env->CallObjectMethod(randomClass, getClassLoaderMethod); gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;) Ljava/lang/Class;" ); return JNI_VERSION_1_6; } jclass findClass(const char* name) { return static_cast<jclass>(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name))); } JNIEnv* getEnv() { JNIEnv *env; int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6); if(status < 0) { status = gJvm->AttachCurrentThread(&env, NULL); if(status < 0) { return nullptr; } } return env; }Copy the code
No pending exception expected: java.lang.ClassNotFoundException: Didn't find class "com.qingkouwei.foundclassdemo.TestClass" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, 
Copy the code

Stackoverflow.com/questions/1…

5. Return value error

On other platforms, such as Linux, we declare that the return type is int. The actual function body does not return, which may be fine, but the Android platform will crash directly.

2022-03-07 15:09:01.152 16695-16695/com.qingkouwei.foundclassdemo A/libc: Fatal signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0x7656c5c5e4 in tid 16695 (.foundclassdemo), pid 16695 (.foundclassdemo)
2022-03-07 15:09:01.157 16639-16881/? E/SecurityComp10105306: EncryptUtil: exception : Failed resolution of: Lorg/bouncycastle/crypto/engines/AESEngine; , you should implementation bcprov-jdk15on library
2022-03-07 15:09:01.222 16908-16908/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2022-03-07 15:09:01.222 16908-16908/? A/DEBUG: Build fingerprint: 'HONOR/YAL-AL00/HWYAL:10/HUAWEIYAL-AL00/10.1.0.162C00:user/release-keys'
2022-03-07 15:09:01.222 16908-16908/? A/DEBUG: Revision: '0'
2022-03-07 15:09:01.222 16908-16908/? A/DEBUG: ABI: 'arm64'
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG: SYSVMTYPE: Maple
    APPVMTYPE: Art
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG: Timestamp: 2022-03-07 15:09:01+0800
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG: pid: 16695, tid: 16695, name: .foundclassdemo  >>> com.qingkouwei.foundclassdemo <<<
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG: uid: 10616
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG: signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0x7656c5c5e4
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x0  000000000000006a  x1  0000007fd6d0b8e0  x2  0000000000000004  x3  0000000000000005
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x4  0000000000000000  x5  4008000000000000  x6  0000000000000000  x7  7f7f7f7f7f7f7f7f
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x8  cefdb6c250ecaf4a  x9  cefdb6c250ecaf4a  x10 00000076f406305c  x11 000000000000003b
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x12 0000000000000018  x13 ffffffffffffffff  x14 ffffffffff000000  x15 ffffffffffffffff
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x16 00000076f406a8f8  x17 00000076f5a4d560  x18 00000076f8cbe000  x19 0000007672210800
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x20 0000000000000000  x21 0000007672210800  x22 0000007fd6d0c450  x23 000000766176c9cb
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x24 0000000000000008  x25 00000076f7e51020  x26 00000076722108b0  x27 0000000000000002
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     x28 0000007fd6d0c1e0  x29 0000007fd6d0c160
2022-03-07 15:09:01.226 16908-16908/? A/DEBUG:     sp  0000007fd6d0c0b0  lr  0000007656c5c5e4  pc  0000007656c5c5e4
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG: backtrace:
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #00 pc 00000000000025e4  /data/app/com.qingkouwei.foundclassdemo-9j6a3XxFGTn9Cw9oVWDDpg==/lib/arm64/libnative-lib.so (myFindClass+344) (BuildId: c9adfab317deb3b439ef1646bc9b03951ef68837)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #01 pc 0000000000002c30  /data/app/com.qingkouwei.foundclassdemo-9j6a3XxFGTn9Cw9oVWDDpg==/lib/arm64/libnative-lib.so (BuildId: c9adfab317deb3b439ef1646bc9b03951ef68837)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #02 pc 0000000000150350  /apex/com.android.runtime/lib64/libart.so (art_quick_generic_jni_trampoline+144) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #03 pc 0000000000147334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #04 pc 00000000001561b4  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+252) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #05 pc 00000000002fd900  /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #06 pc 00000000002f8bd0  /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+912) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #07 pc 00000000005cb550  /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+648) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #08 pc 0000000000141814  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #09 pc 0000000000123f60  [anon:dalvik-classes.dex extracted in memory from /data/app/com.qingkouwei.foundclassdemo-9j6a3XxFGTn9Cw9oVWDDpg==/base.apk] (com.qingkouwei.foundclassdemo.MainActivity$1.onClick+12)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #10 pc 00000000005cd060  /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterface+1752) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #11 pc 0000000000141a14  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #12 pc 000000000023af0c  /system/framework/framework.jar (android.view.View.performClick+40)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #13 pc 00000000005cb860  /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+1432) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #14 pc 0000000000141814  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #15 pc 000000000023af56  /system/framework/framework.jar (android.view.View.performClickInternal+6)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #16 pc 00000000005cdbfc  /apex/com.android.runtime/lib64/libart.so (MterpInvokeDirect+1168) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #17 pc 0000000000141914  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_direct+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #18 pc 00000000002363fc  /system/framework/framework.jar (android.view.View.access$3600)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #19 pc 00000000005ce408  /apex/com.android.runtime/lib64/libart.so (MterpInvokeStatic+1136) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #20 pc 0000000000141994  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_static+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #21 pc 000000000021320c  /system/framework/framework.jar (android.view.View$PerformClick.run+56)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #22 pc 00000000005cd060  /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterface+1752) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #23 pc 0000000000141a14  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #24 pc 000000000030cc4c  /system/framework/framework.jar (android.os.Handler.handleCallback+4)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #25 pc 00000000005ce408  /apex/com.android.runtime/lib64/libart.so (MterpInvokeStatic+1136) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #26 pc 0000000000141994  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_static+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #27 pc 000000000030cab8  /system/framework/framework.jar (android.os.Handler.dispatchMessage+8)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #28 pc 00000000005cb860  /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+1432) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #29 pc 0000000000141814  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #30 pc 0000000000337c30  /system/framework/framework.jar (android.os.Looper.loop+480)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #31 pc 00000000005ce408  /apex/com.android.runtime/lib64/libart.so (MterpInvokeStatic+1136) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #32 pc 0000000000141994  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_static+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #33 pc 00000000001abfe0  /system/framework/framework.jar (android.app.ActivityThread.main+1372)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #34 pc 00000000002ce22c  /apex/com.android.runtime/lib64/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.10887373532384510885+320) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #35 pc 00000000005bc090  /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1012) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #36 pc 0000000000150468  /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #37 pc 00000000001475b8  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_static_stub+568) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #38 pc 00000000001561d4  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+284) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #39 pc 00000000004d8820  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #40 pc 00000000004da248  /apex/com.android.runtime/lib64/libart.so (art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long)+1476) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #41 pc 000000000046412c  /apex/com.android.runtime/lib64/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)+52) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #42 pc 00000000000f8c34  /system/framework/arm64/boot.oat (art_jni_trampoline+180) (BuildId: 8fb9eb57b3ea725573d56f165d17f78dd54965d7)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #43 pc 0000000000147334  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #44 pc 00000000001561b4  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+252) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #45 pc 00000000002fd900  /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #46 pc 00000000002f8bd0  /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+912) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #47 pc 00000000005cb550  /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+648) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #48 pc 0000000000141814  /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #49 pc 000000000040010e  /system/framework/framework.jar (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+22)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #50 pc 00000000002ce22c  /apex/com.android.runtime/lib64/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.10887373532384510885+320) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #51 pc 00000000005bc090  /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1012) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #52 pc 0000000000150468  /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #53 pc 0000000000b253bc  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteInit.main+3660) (BuildId: 839677a7635b67b1b883c48b6ed1ea5c4a581790)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #54 pc 00000000001475b8  /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_static_stub+568) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #55 pc 00000000001561d4  /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+284) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #56 pc 00000000004d8820  /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #57 pc 00000000004d848c  /apex/com.android.runtime/lib64/libart.so (art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+408) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #58 pc 00000000003d7cf8  /apex/com.android.runtime/lib64/libart.so (art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+660) (BuildId: 08543716770b195bd10fafbe11bb5052)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #59 pc 00000000001015c4  /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+116) (BuildId: 034c759a360c29cae9a101b25604f692)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #60 pc 0000000000104c48  /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+1248) (BuildId: 034c759a360c29cae9a101b25604f692)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #61 pc 00000000000034e0  /system/bin/app_process64 (main+1168) (BuildId: e844be217eb39b34490d3798328d1f12)
2022-03-07 15:09:01.375 16908-16908/? A/DEBUG:       #62 pc 000000000006b108  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108) (BuildId: b91c775ccc9b0556e91bc575a2511cd0)
2022-03-07 15:09:01.405 17145-17756/? E/X509CertUtil: can not open cbg root cer
Copy the code

6. Other errors described in the NDK guide

6.1 minSdkVersionIs higher than the device’S API level

Build with the NDK based on a different API level than compileSdkVersion in Java. The NDK API level is the lowest API level supported by your application. In ndK-build, this refers to the APP_PLATFORM setting. For CMake, this means -dandroid_platform. (If you are using externalNativeBuild, your minSdkVersion will be used automatically.)

System resolution of function references usually occurs when the library is loaded, not when it is first called, so aN API that does not always exist and whose use is protected by API-level checking will not be referenced. If an API is referenced, then the API must exist.

Problem: THE NDK API level is higher than that supported by the device.

Solution: Set the NDK API level (APP_PLATFORM) to the lowest Android version supported by your application.

6.2 I couldn’t findrandsymbol

For the following error log message, see this detailed Stack Overflow solution.

UnsatisfiedLinkError: dlopen failed: cannot locate symbol "rand"
Copy the code

6.3 No pair is defined__atomic_*A reference to the

Problem: Some ABIs require Libatomic to provide some implementation for atomic operations.

Solution: Add -latomic when linking.

For the following error message:

error: undefined reference to '__atomic_exchange_4'
Copy the code

The actual symbol here could be any symbol prefixed with __atomic_. Nk-build and CMake will take care of this for us. For other build systems, we need to do this manually.)

6.3 RTTI/ exception catching cannot run across library boundaries

Problem: Cannot catch exceptions when thrown across shared library boundaries or when dynamic_cast fails.

Solution: Add a key function for our type. A key function is the first impure extraneous virtual function of a type. Refer to the discussion on question 533.

The C++ ABI specifies that two objects have the same type if and only if their type_info Pointers are the same. An exception is caught only if the captured Type_INFO matches the exception thrown. This rule also applies to dynamic_cast.

If a type does not have a key function, its TypeInfo is emitted as a weak symbol and the matching type information is merged when the library is loaded. If the library is loaded dynamically after the executable has finished loading (that is, through dlopen or System.loadLibrary), the loader may not be able to merge the type information of the loaded library. When this happens, the two types are not considered equal.

For non-polymorphic types, types cannot have key functions. For non-polymorphic types, RTTI is redundant because type equivalence can be determined at compile time using STD :: is_SAME.

6.4 Using mismatched prebuilt libraries

Special care needs to be taken when using pre-built libraries (often third-party libraries) in our application. In general, please note the following rules:

  • The lowest API level for the generated application is the maximum minSdkVersion value for all the libraries applied.

    If our minSdkVersion is 16 but uses a pre-built library built according to 21, the minimum API level for the generated application is 21. If the prebuilt library is static, violations of this rule will be shown at build time, but only when the prebuilt shared library is running.

  • All libraries should be generated using the same NDK version.

    This rule is a little more flexible than most because of the rarity of violations, but it does not guarantee compatibility between libraries built with different Major versions of the NDK. The C++ ABI is not stable and has changed in the past.

  • Applications with multiple shared libraries must use a shared STL.

    In the case of STL mismatches, the resulting problem can be avoided by careful manipulation, but it is best to avoid the problem directly. To avoid this problem, it is best to avoid using multiple shared libraries in your application.

7. To summarize

This article introduces common issues in JNI development, such as versioning issues, locating symbol failures, and function implementation differences between platforms. You can continue to maintain and iterate this document.