当前位置: 首页 > java >正文

Dalvik虚拟机和ART虚拟机

目录

一,背景知识

1.1 Dalvik虚拟机概述

1.2 Dalvik虚拟机的启动过程

Dalvik虚拟机的运行过程


一,背景知识

Android应用程序是运行在Dalvik虚拟机里面的,并且每一个应用程序对应有一个单独的Dalvik虚拟机实例。Android应用程序中的Dalvik虚拟机实例实际上是从Zygote进程的地址空间拷贝而来的,这样就可以加快Android应用程序的启动速度。Dalvik虚拟机与Java虚拟机共享有差不多的特性,例如,它们都是解释执行,并且支持即时编译(JIT)、垃圾收集(GC)、Java本地方法调用(JNI)和Java远程调试协议(JDWP)等,差别在于两者执行的指令集是不一样的,并且前者的指令集是基本寄存器的,而后者的指令集是基于堆栈的。
本系列文章主要将Dalvik虚拟机的内存管理、垃圾收集、即时编译、Java本地调用、进程和线程管理等。理解Dalvik虚拟机的上述实现细节,有助于在运行时修改程序的行为,例如,拦截Java函数的调用

  • Dalvik虚拟机概述
  • Dalvik虚拟机的启动过程
  • Dalvik虚拟机的运行过程
  • JNI函数的注册过程
  • Dalvik虚拟机进程
  • Dalvik虚拟机线程

1.1 Dalvik虚拟机概述

Dalvik虚拟机由Dan Bornstein开发,名字来源于他的祖先曾经居住过的位于冰岛的同名小渔村
Dalvik虚拟机起源于Apache Harmony项目,后者是由Apache软件基金会主导的,目标是实现一个独立的、兼容JDK 5的虚拟机,并根据Apache License v2发布

Dalvik虚拟机与Java虚拟机的区别

  • 基于堆栈的Java指令(1个字节)和基于寄存器的Dalvik指令(2、4或者6个字节)各有优劣
  • 一般而言,执行同样的功能, Java虚拟机需要更多的指令(主要是load和store指令),而Dalvik虚拟机需要更多的指令空间
  • 需要更多指令意味着要多占用CPU时间,而需要更多指令空间意味着指令缓冲(i-cache)更易失效
  • Dalvik虚拟机使用dex(Dalvik Executable)格式的类文件,而Java虚拟机使用class格式的类文件
  • 一个dex文件可以包含若干个类,而一个class文件只包括一个类
  • 由于一个dex文件可以包含若干个类,因此它可以将各个类中重复的字符串只保存一次,从而节省了空间,适合在内存有限的移动设备使用
  • 一般来说,包含有相同类的未压缩dex文件稍小于一个已经压缩的jar文件

Dex文件的优化

  • 将invoke-virtual指令中的method index转换为vtable index – 加快虚函数调用速度
  • 将get/put指令中的field index转换为byte offset – 加快实例成员变量访问速度
  • 将boolean/byte/char/short变种的get/put指令统一转换为32位的get/put指令 – 减小VM解释器的大小,从而更有效地利用CPU的i-cache
  • 将高频调用的函数,例如String.length,转换为inline函数 – 消除函数调用开销
  • 移除空函数,例如Object.<init> -- 消除空函数调用
  • 将可以预先计算的数据进行预处理,例如预先生成VM根据class name查询class的hash table – 节省Dex文件加载时间以及内存占用空间
  • 将invoke-virtual指令中的method index转换为vtable index

Dex文件的优化时机

  • VM在运行时即时优化,例如使用DexClassLoader动态加载dex文件时。这时候需要指定一个当前进程有写权限的用来保存odex的目录。
  • APP安装时由具有root权限的installd优化。这时候优化产生的odex文件保存在特权目录/data/dalvik-cache中。
  • 编译时优化。这时候编译出来的jar/apk里面的classes.dex被提取并且优化为classes.odex保存在原jar/apk所在目录,打包在system image中。

内存管理

  • Java Object Heap
    大小受限,16M/24M/32M/48M/…
  • Bitmap Memory(External Memroy):
    大小计入Java Object Heap
  • Native Heap
    大小不受限

Java Object Heap

  • 用来分配Java对象。Dalvik虚拟机在启动的时候,可以通过-Xms和-Xmx选项来指定Java Object Heap的最小值和最大值。
  • Java Object Heap的最小和最大默认值为2M和16M。但是厂商会根据手机的配置情况进行调整,例如,G1、Droid、Nexus One和Xoom的Java Object Heap的最大值分别为16M、24M、32M 和48M。
  • 通过ActivityManager.getMemoryClass可以获得Dalvik虚拟机的Java Object Heap的最大值。

Bitmap Memory

  • 用来处理图像。在HoneyComb之前,Bitmap Memory是在Native Heap中分配的,但是这部分内存同样计入Java Object Heap中。这就是为什么我们在调用BitmapFactory相关的接口来处理大图像时,会抛出一个OutOfMemoryError异常的原因:java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  • 在HoneyComb以及更高的版本中,Bitmap Memory就直接是在Java Object Heap中分配了,这样就可以直接接受GC的管理

Native Heap

  • 在Native Code中使用malloc等分配出来的内存,这部分内存不受Java Object Heap的大小限制。
  • 注意,不要因为Native Heap可以自由使用就滥用,因为滥用Native Heap会导致系统可用内存急剧减少,从而引发系统采取激进的措施来Kill掉某些进程,用来补充可用内存,这样会影响系统体验。

垃圾收集(GC)

  • Step 1: Mark,使用RootSet标记对象引用

  • Step 2: Sweep,回收没有被引用的对象
    GingerBread之前

  • Stop-the-word,也就是垃圾收集线程在执行的时候,其它的线程都停止

  • Full heap collection,也就是一次收集完全部的垃圾

  • 一次垃圾收集造成的程序中止时间通常都大于100ms
    GingerBread之后

  • Cocurrent,也就是大多数情况下,垃圾收集线程与其它线程是并发执行的

  • Partial collection,也就是一次可能只收集一部分垃圾

  • 一次垃圾收集造成的程序中止时间通常都小于5ms

即时编译(JIT)

  • 从2.2开始支持JIT,并且是可选的,编译时通过WITH_JIT宏进行控制

  • 基于执行路径(Executing Path)对热门的代码片断进行优化(Trace JIT),传统的Java虚拟机以Method为单位进行优化(Method JIT)

  • 可以利用运行时信息进行激进优化,获得比静态编译语言更高的性能,如Lazy Unlocking机制

支持JDWP(Java Debug Wire Protocol)协议

  • 每一个Dalvik虚拟机进程都都提供有一个端口来供调试器连接
  • DDMS提供有一个转发端口8870,通过它可以同时调试多个Dalvik虚拟机进程

1.2 Dalvik虚拟机的启动过程

Dalvik虚拟机由Zygote进程启动,然后再复制到System Server进程和应用程序进程

startVM的过程中会创建一个JavaVMExt,并且该JavaVMExt关联有一个JNIInvokeInterface,Native Code通过它来访问Dalvik虚拟机

struct _JavaVM {const struct JNIInvokeInterface* functions;#if defined(__cplusplus)jint DestroyJavaVM(){ return functions->DestroyJavaVM(this); }jint AttachCurrentThread(JNIEnv** p_env, void* thr_args){ return functions->AttachCurrentThread(this, p_env, thr_args); }jint DetachCurrentThread(){ return functions->DetachCurrentThread(this); }jint GetEnv(void** env, jint version){ return functions->GetEnv(this, env, version); }jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args){ return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
#endif /*__cplusplus*/
};

JNINativeInterface核心代码
std::unique_ptr<JavaVMExt> JavaVMExt::Create(Runtime* runtime,const RuntimeArgumentMap& runtime_options,std::string* error_msg) NO_THREAD_SAFETY_ANALYSIS {std::unique_ptr<JavaVMExt> java_vm(new JavaVMExt(runtime, runtime_options, error_msg));if (java_vm && java_vm->globals_.IsValid() && java_vm->weak_globals_.IsValid()) {return java_vm;}return nullptr;
}

虚拟机启动流程

struct JNINativeInterface {void*       reserved0;void*       reserved1;void*       reserved2;void*       reserved3;jint        (*GetVersion)(JNIEnv *);jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,jsize);jclass      (*FindClass)(JNIEnv*, const char*);jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);jfieldID    (*FromReflectedField)(JNIEnv*, jobject);/* spec doesn't show jboolean parameter */jobject     (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);jclass      (*GetSuperclass)(JNIEnv*, jclass);jboolean    (*IsAssignableFrom)(JNIEnv*, jclass, jclass);/* spec doesn't show jboolean parameter */jobject     (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);jint        (*Throw)(JNIEnv*, jthrowable);jint        (*ThrowNew)(JNIEnv *, jclass, const char *);jthrowable  (*ExceptionOccurred)(JNIEnv*);void        (*ExceptionDescribe)(JNIEnv*);void        (*ExceptionClear)(JNIEnv*);void        (*FatalError)(JNIEnv*, const char*);jint        (*PushLocalFrame)(JNIEnv*, jint);jobject     (*PopLocalFrame)(JNIEnv*, jobject);jobject     (*NewGlobalRef)(JNIEnv*, jobject);void        (*DeleteGlobalRef)(JNIEnv*, jobject);void        (*DeleteLocalRef)(JNIEnv*, jobject);jboolean    (*IsSameObject)(JNIEnv*, jobject, jobject);jobject     (*NewLocalRef)(JNIEnv*, jobject);jint        (*EnsureLocalCapacity)(JNIEnv*, jint);jobject     (*AllocObject)(JNIEnv*, jclass);jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);jobject     (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);jobject     (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);jclass      (*GetObjectClass)(JNIEnv*, jobject);jboolean    (*IsInstanceOf)(JNIEnv*, jobject, jclass);jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);jobject     (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jobject     (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jobject     (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jboolean    (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jboolean    (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jboolean    (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jbyte       (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jbyte       (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jbyte       (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jchar       (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jchar       (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jchar       (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jshort      (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jshort      (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jshort      (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jint        (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jint        (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jint        (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jlong       (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jlong       (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jlong       (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jfloat      (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jfloat      (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jfloat      (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jdouble     (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);jdouble     (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);jdouble     (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);void        (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,jmethodID, ...);void        (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,jmethodID, va_list);void        (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass,jmethodID, jvalue*);jfieldID    (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);jobject     (*GetObjectField)(JNIEnv*, jobject, jfieldID);jboolean    (*GetBooleanField)(JNIEnv*, jobject, jfieldID);jbyte       (*GetByteField)(JNIEnv*, jobject, jfieldID);jchar       (*GetCharField)(JNIEnv*, jobject, jfieldID);jshort      (*GetShortField)(JNIEnv*, jobject, jfieldID);jint        (*GetIntField)(JNIEnv*, jobject, jfieldID);jlong       (*GetLongField)(JNIEnv*, jobject, jfieldID);jfloat      (*GetFloatField)(JNIEnv*, jobject, jfieldID);jdouble     (*GetDoubleField)(JNIEnv*, jobject, jfieldID);void        (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);void        (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);void        (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);void        (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar);void        (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort);void        (*SetIntField)(JNIEnv*, jobject, jfieldID, jint);void        (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong);void        (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat);void        (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble);jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);jobject     (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);jobject     (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);jboolean    (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,va_list);jboolean    (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID,jvalue*);jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);jbyte       (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);jbyte       (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);jchar       (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);jchar       (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);jshort      (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);jshort      (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);jint        (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);jint        (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jlong       (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);jlong       (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);jlong       (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);jfloat      (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);jfloat      (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);jdouble     (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);jdouble     (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);void        (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);jfieldID    (*GetStaticFieldID)(JNIEnv*, jclass, const char*,const char*);jobject     (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);jboolean    (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID);jbyte       (*GetStaticByteField)(JNIEnv*, jclass, jfieldID);jchar       (*GetStaticCharField)(JNIEnv*, jclass, jfieldID);jshort      (*GetStaticShortField)(JNIEnv*, jclass, jfieldID);jint        (*GetStaticIntField)(JNIEnv*, jclass, jfieldID);jlong       (*GetStaticLongField)(JNIEnv*, jclass, jfieldID);jfloat      (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID);jdouble     (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID);void        (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);void        (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean);void        (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);void        (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar);void        (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort);void        (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint);void        (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong);void        (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat);void        (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble);jstring     (*NewString)(JNIEnv*, const jchar*, jsize);jsize       (*GetStringLength)(JNIEnv*, jstring);const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);jstring     (*NewStringUTF)(JNIEnv*, const char*);jsize       (*GetStringUTFLength)(JNIEnv*, jstring);/* JNI spec says this returns const jbyte*, but that's inconsistent */const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);jsize       (*GetArrayLength)(JNIEnv*, jarray);jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject);jobject     (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);void        (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);jbyteArray    (*NewByteArray)(JNIEnv*, jsize);jcharArray    (*NewCharArray)(JNIEnv*, jsize);jshortArray   (*NewShortArray)(JNIEnv*, jsize);jintArray     (*NewIntArray)(JNIEnv*, jsize);jlongArray    (*NewLongArray)(JNIEnv*, jsize);jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,jboolean*, jint);void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,jbyte*, jint);void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,jchar*, jint);void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,jshort*, jint);void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint);void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,jlong*, jint);void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,jfloat*, jint);void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,jdouble*, jint);void        (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*);void        (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*);void        (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*);void        (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*);void        (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*);void        (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*);void        (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*);void        (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*);/* spec shows these without const; some jni.h do, some don't */void        (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*);void        (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*);void        (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*);void        (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*);void        (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);void        (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*);void        (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*);void        (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*);jint        (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,jint);jint        (*UnregisterNatives)(JNIEnv*, jclass);jint        (*MonitorEnter)(JNIEnv*, jobject);jint        (*MonitorExit)(JNIEnv*, jobject);jint        (*GetJavaVM)(JNIEnv*, JavaVM**);void        (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);void        (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);void*       (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*);void        (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint);const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*);void        (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);jweak       (*NewWeakGlobalRef)(JNIEnv*, jobject);void        (*DeleteWeakGlobalRef)(JNIEnv*, jweak);jboolean    (*ExceptionCheck)(JNIEnv*);jobject     (*NewDirectByteBuffer)(JNIEnv*, void*, jlong);void*       (*GetDirectBufferAddress)(JNIEnv*, jobject);jlong       (*GetDirectBufferCapacity)(JNIEnv*, jobject);/* added in JNI 1.6 */jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject);
};

startVM的过程中还会为当前线程关联有一个JNIEnvExt,并且该JNIEnvExt 关联有一个JNINativeInterface,Native Code通过它来调用Java函数或者访问Java对象

Dalvik虚拟机在Zygote进程启动的过程中,还会进一步预加载Java和Android核心类库以及系统资源

Dalvik虚拟机从Zygote进程复制到System Server进程之后,它们就通过COW(Copy On Write)机制共享同一个Dalvik虚拟机实例以及预加载类库和资源

Dalvik虚拟机从Zygote进程复制到应用程序进程之后,它们同样会通过COW(Copy On Write)机制共享同一个Dalvik虚拟机实例以及预加载类库和资源

Dalvik虚拟机的运行过程
  • Dalvik虚拟机在Zygote进程中启动之后,就会以ZygoteInit.main为入口点开始运行
  • Dalvik虚拟机从Zygote进程复制到System Server进程之后,就会以SystemServer.main为入口点开始运行
  • Dalvik虚拟机Zygote进程复制到应用程序进程之后,就会以ActivityThread.main为入口点开始运行
  • 上述入口点都是通过调用JNINativeInterface接口的成员函数CallStaticVoidMethod来进入的
    J
    JNINativeInterface->CallStaticVoidMethod对应的实现为CallStaticVoidMethodV-->InvokeWithVarArgs

http://www.xdnf.cn/news/3806.html

相关文章:

  • ART 下 Dex 加载流程源码分析 和 通用脱壳点
  • 【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?
  • 学习黑客Linux权限
  • 【中间件】brpc_基础_用户态线程中断
  • LeetCode每日一题5.4
  • 架构思维:利用全量缓存架构构建毫秒级的读服务
  • 2001-2023年 上市公司-企业广告支出数据-社科数据
  • 使用宝塔面板、青龙面板实现定时推送功能
  • 【数据结构】稀疏矩阵的快速转置
  • 单细胞测序数据分析试验设计赏析(二)
  • Android 输入控件事件使用示例
  • 信息系统监理师第二版教材模拟题第一组(含解析)
  • HTML学习笔记(7)
  • PostgreSQL 的 ANALYZE 命令
  • PostgreSQL 查看索引碎片的方法
  • 论文阅读笔记——STDArm
  • PostgreSQL 判断索引是否重建过的方法
  • 4电池_基于开关电容的均衡
  • Ubuntu 系统上广受好评的浏览器推荐
  • 蘑菇管理——AI与思维模型【94】
  • 【翻译、转载】使用 LLM 构建 MCP
  • 【五一培训】Day 3
  • 机器学习+多目标优化的算法如何设计?
  • AI跑得快,MCP来加速——模型计算平台在训练与推理中的硬核作用
  • 位图的实现和拓展
  • P1603 斯诺登密码详解
  • 【项目篇之统一内存操作】仿照RabbitMQ模拟实现消息队列
  • Android运行时ART加载类和方法的过程分析
  • Python-Django系列—视图
  • 8.2 GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析