Android JNI原理

Posted xhBruce

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android JNI原理相关的知识,希望对你有一定的参考价值。

android JNI原理

android12-release


1. Java Native Interface

  JNI(Java Native Interface,Java本地接口),用于打通Java层与Native(C/C++)层。这不是Android系统所独有的,而是Java所有(Java本地调用(JNI))。通过JNI为上层Java提供各种服务,保证跨平台性。

2. Android首个JNI实例Zygote进程

  Android系统在启动启动过程Kernel->init进程->Zygote进程,Zygote进程是由init进程fork第一个横穿Java和C/C++的进程。Zygote进程启动过程中通过AndroidRuntime::start中startVm创建虚拟机,紧接着调用startReg完成虚拟机中的JNI方法注册。

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)

    // ... ...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) 
        return;
    
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) 
        ALOGE("Unable to register all android natives\\n");
        return;
    
    // ... ...

2.1 startReg

  • register_jni_procs 循环调用gRegJNI数组成员所对应的方法
  • gRegJNI数组的每个成员代表一个类文件的jni映射
  • REG_JNI是一个宏定义,REG_JNI(register_com_android_internal_os_RuntimeInit)调用到register_com_android_internal_os_RuntimeInit方法
#ifdef NDEBUG
    #define REG_JNI(name)       name 
    struct RegJNIRec 
        int (*mProc)(JNIEnv*);
    ;
#else
    #define REG_JNI(name)       name, #name 
    struct RegJNIRec 
        int (*mProc)(JNIEnv*);
        const char* mName;
    ;
#endif

static int
 register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)

    for (size_t i = 0; i < count; i++) 
        if (array[i].mProc(env) < 0) 
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\\n", array[i].mName);
#endif
            return -1;
        
    
    return 0;


static const RegJNIRec gRegJNI[] = 
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        // ... ...
        REG_JNI(register_android_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        REG_JNI(register_android_os_Binder),
        // ... ...
        REG_JNI(register_android_os_MessageQueue),
        // ... ...
        REG_JNI(register_com_android_internal_os_Zygote),
        REG_JNI(register_com_android_internal_os_ZygoteInit),
        // ... ...
        REG_JNI(register_android_hardware_SensorManager),
        // ... ...
        REG_JNI(register_android_view_InputChannel),
        REG_JNI(register_android_view_InputEventReceiver),
        REG_JNI(register_android_view_InputEventSender),
        REG_JNI(register_android_view_InputQueue),
        REG_JNI(register_android_view_KeyEvent),
        REG_JNI(register_android_view_MotionEvent),
       // ... ...
;

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)

    // ... ...
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) 
        env->PopLocalFrame(NULL);
        return -1;
    
    // ... ...

2.2 Framework层JNI对应Nativec层位置

Java本地调用(JNI) 文件对应[java包名]_[java类名].cpp,与AndroidRuntime注册REG_JNI不同,通过调用System.loadLibrary()加载so库方式注册

Android JNI 常见目录:

  • /framework/base/core/jni/
  • /framework/base/services/core/jni/
  • /framework/base/media/jni/

3. SystemServer加载libandroid_servers.so

  • System.loadLibrary("android_servers")加载调用到so库中JNI_OnLoad()方法

frameworks/base/services/Android.bp
frameworks/base/services/java/com/android/server/SystemServer.java

private void run() 
        // ... ...
        // Initialize native services.
        System.loadLibrary("android_servers");
        // ... ...

  • JNI_OnLoad()注册相关系统服务JNI
注册JNIFramework
register_android_server_InputManagercom_android_server_input_InputManagerService.cppInputManagerService.java
register_android_server_sensor_SensorServicecom_android_server_sensor_SensorService.cppSensorService.java

frameworks/base/services/core/jni/onload.cpp

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)

    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) 
        ALOGE("GetEnv failed!");
        return result;
    
    ALOG_ASSERT(env, "Could not retrieve the env!");

    register_android_server_broadcastradio_BroadcastRadioservice(env);
    register_android_server_broadcastradio_Tuner(vm, env);
    register_android_server_PowerManagerService(env);
    register_android_server_PowerStatsService(env);
    register_android_server_HintManagerService(env);
    register_android_server_SerialService(env);
    register_android_server_InputManager(env);
    register_android_server_LightsService(env);
    register_android_server_UsbDeviceManager(env);
    register_android_server_UsbMidiDevice(env);
    register_android_server_UsbAlsaJackDetector(env);
    register_android_server_UsbHostManager(env);
    register_android_server_vr_VrManagerService(env);
    register_android_server_vibrator_VibratorController(vm, env);
    register_android_server_vibrator_VibratorManagerService(vm, env);
    register_android_server_SystemServer(env);
    register_android_server_location_GnssLocationProvider(env);
    register_android_server_connectivity_Vpn(env);
    register_android_server_devicepolicy_CryptoTestHelper(env);
    register_android_server_ConsumerIrService(env);
    register_android_server_BatteryStatsService(env);
    register_android_server_tv_TvUinputBridge(env);
    register_android_server_tv_TvInputHal(env);
    register_android_server_PersistentDataBlockService(env);
    register_android_server_HardwarePropertiesManagerService(env);
    register_android_server_storage_AppFuse(env);
    register_android_server_SyntheticPasswordManager(env);
    register_android_graphics_GraphicsStatsService(env);
    register_android_hardware_display_DisplayViewport(env);
    register_android_server_net_NetworkStatsFactory(env);
    register_android_server_net_NetworkStatsService(env);
    register_android_server_am_CachedAppOptimizer(env);
    register_android_server_am_LowMemDetector(env);
    register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
    register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(env);
    register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
    register_android_server_AdbDebuggingManager(env);
    register_android_server_FaceService(env);
    register_android_server_GpuService(env);
    register_android_server_stats_pull_StatsPullAtomService(env);
    register_android_server_sensor_SensorService(vm, env);
    return JNI_VERSION_1_4;

3.1 例如InputManagerService服务

  • JNI_OnLoad() -> register_android_server_InputManager
  • jniRegisterNativeMethods通过AndroidRuntime最终调用到JNIHelp.h、jni.hRegisterNatives()

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

int register_android_server_InputManager(JNIEnv* env) 
    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
            gInputManagerMethods, NELEM(gInputManagerMethods));
    (void) res;  // Faked use when LOG_NDEBUG.
    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
    // ... ...
    return 0;


static const JNINativeMethod gInputManagerMethods[] = 
        /* name, signature, funcPtr */
        "nativeInit",
         "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/"
         "MessageQueue;)J",
         (void*)nativeInit,
        "nativeStart", "(J)V", (void*)nativeStart,
        // ... ...
        "nativeEnableSensor", "(JIIII)Z", (void*)nativeEnableSensor,
        "nativeDisableSensor", "(JII)V", (void*)nativeDisableSensor,
        "nativeFlushSensor", "(JII)Z", (void*)nativeFlushSensor,
;
  • JNIEnv 是指线程上下文环境,每个线程有且只有一个JNIEnv实例

frameworks/base/core/jni/AndroidRuntime.cpp
libnativehelper/include/nativehelper/JNIHelp.h

/*
 * Register one or more native methods with a particular class.  "className" looks like
 * "java/lang/String". Aborts on failure, returns 0 on success.
 */
[[maybe_unused]] static int jniRegisterNativeMethods(JNIEnv* env, const char* className,
                                                     const JNINativeMethod* methods,
                                                     int numMethods) 
    using namespace android::jnihelp;
    jclass clazz = env->FindClass(className);
    if (clazz == NULL) 
        __android_log_assert("clazz == NULL", "JNIHelp",
                             "Native registration unable to find class '%s'; aborting...",
                             className);
    
    int result = env->RegisterNatives(clazz, methods, numMethods);
    env->DeleteLocalRef(clazz);
    if (result == 0) 
        return 0;
    

    // Failure to register natives is fatal. Try to report the corresponding exception,
    // otherwise abort with generic failure message.
    jthrowable thrown = env->ExceptionOccurred();
    if (thrown != NULL) 
        struct ExpandableString summary;
        ExpandableStringInitialize(&summary);
        if (GetExceptionSummary(env, thrown, &summary)) 
            __android_log_print(ANDROID_LOG_FATAL, "JNIHelp", "%s", summary.data);
        
        ExpandableStringRelease(&summary);
        env->DeleteLocalRef(thrown);
    
    __android_log_print(ANDROID_LOG_FATAL, "JNIHelp",
                        "RegisterNatives failed for '%s'; aborting...", className);
    return result;

libnativehelper/include_jni/jni.h

jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
    jint nMethods)
 return functions->RegisterNatives(this, clazz, methods, nMethods); 

以上是关于Android JNI原理的主要内容,如果未能解决你的问题,请参考以下文章

Android底层笔记:APP通过JNI调用动态库.so

jni2

Android高级NDK/JNI编程技术基础介绍

Android 开创java世界(JNI Invocation API)

Android Studio NDK 入门教程--JNI签名验证防止恶意调用

Android-JNI开发系列《十一》实践-利用Android C源码实现GIF图片的播放