Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發環境 >> 深入理解Dalvik虛擬機

深入理解Dalvik虛擬機

編輯:Android開發環境

  Dalvik的指令執行是解釋器+JIT的方式,解釋器就是虛擬機來對Javac編譯出來的字節碼,做譯碼、執行,而不是轉化成CPU的指令集,由CPU來做譯碼,執行。可想而知,解釋器的效率是相對較低的,所以出現了JIT(Just In Time),JIT是將執行次數較多的函數,做即時編譯,在運行時刻,編譯成本地目標代碼,JIT可以看成是解釋器的一個補充優化。再之後又出現了Art虛擬機的AOT(Ahead Of Time)模式,做靜態編譯,在Apk安裝的時候就會做字節碼的編譯,從而效率直逼靜態語言。

  Java所有的方法都是類方法,因此Dalvik的字節碼執行就兩種,一是類的Method,包括靜態和非靜態,兩者的差距也就是有沒有this參數,二就是類的初始化代碼,就是類加載的時候,成員變量的初始化以及顯式的類初始化塊代碼。

  其中類的初始化代碼在dalvik/vm/oo/Class.cpp的dvmInitClass:

C++代碼
  1. bool dvmInitClass(ClassObject* clazz)    
  2. {    
  3.     ...    
  4.     dvmLockObject(self, (Object*) clazz);    
  5.     ...    
  6.     android_atomic_release_store(CLASS_INITIALIZING,    
  7.                                  (int32_t*)(void*)&clazz->status);    
  8.     dvmUnlockObject(self, (Object*) clazz);    
  9.     ...    
  10.     initSFields(clazz);    
  11.     
  12.     /* Execute any static initialization code.  
  13.      */    
  14.     method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");    
  15.     if (method == NULL) {    
  16.         LOGVV("No <clinit> found for %s", clazz->descriptor);    
  17.     } else {    
  18.         LOGVV("Invoking %s.<clinit>", clazz->descriptor);    
  19.         JValue unused;    
  20.         dvmCallMethod(self, method, NULL, &unused);    
  21.     }    
  22.     ...    
  23. }   

  從代碼可見,類初始化的主要代碼邏輯包括:

  類對象加鎖,所以類的加載是單線程的

  初始化static成員(initSFields)

  調用<cinit>,靜態初始化塊

  類的初始化塊代碼在<cinit>的成員函數裡。可見Dalvik的字節碼解釋,本質上還是類成員函數的解釋執行。

  虛擬機以Method作為解釋器的執行單元,其入口就統一為dvmCallMethod,該函數的定義在dalvik/vm/interp/Stack.cpp裡。

C++代碼
  1. void dvmCallMethod(Thread* self, const Method* method, Object* obj,    
  2.     JValue* pResult, ...)    
  3. {    
  4.     va_list args;    
  5.     va_start(args, pResult);    
  6.     dvmCallMethodV(self, method, obj, false, pResult, args);    
  7.     va_end(args);    
  8. }    
  9.     
  10. void dvmCallMethodV(Thread* self, const Method* method, Object* obj,    
  11.     bool fromJni, JValue* pResult, va_list args)    
  12. {    
  13.    ...    
  14.     if (dvmIsNativeMethod(method)) {    
  15.         TRACE_METHOD_ENTER(self, method);    
  16.         /*  
  17.          * Because we leave no space for local variables, "curFrame" points  
  18.          * directly at the method arguments.  
  19.          */    
  20.         (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,    
  21.                               method, self);    
  22.         TRACE_METHOD_EXIT(self, method);    
  23.     } else {    
  24.         dvmInterpret(self, method, pResult);    
  25.     }    
  26.    …    
  27. }

  Java的Method有native函數和非native函數,native的函數的代碼段是在so裡,是本地指令集而非虛擬機的字節碼。

  虛擬機以Method作為解釋器的執行單元,其入口就統一為dvmCallMethod,該函數的定義在dalvik/vm/interp/Stack.cpp裡。

C++代碼
  1. void dvmCallMethod(Thread* self, const Method* method, Object* obj,    
  2.     JValue* pResult, ...)    
  3. {    
  4.     va_list args;    
  5.     va_start(args, pResult);    
  6.     dvmCallMethodV(self, method, obj, false, pResult, args);    
  7.     va_end(args);    
  8. }    
  9.     
  10. void dvmCallMethodV(Thread* self, const Method* method, Object* obj,    
  11.     bool fromJni, JValue* pResult, va_list args)    
  12. {    
  13.    ...    
  14.         if (dvmIsNativeMethod(method)) {    
  15.         TRACE_METHOD_ENTER(self, method);    
  16.         /*  
  17.          * Because we leave no space for local variables, "curFrame" points  
  18.          * directly at the method arguments.  
  19.          */    
  20.         (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,    
  21.                               method, self);    
  22.         TRACE_METHOD_EXIT(self, method);    
  23.     } else {    
  24.         dvmInterpret(self, method, pResult);    
  25.  }    
  26.    …    
  27. }

  如果method是個native的函數,那麼就直接調用nativeFunc這個函數指針,否則就調用dvmInterpret代碼,dvmInterpret就是解釋器的入口。

  如果把Dalvik函數執行的調用棧畫出來,我們會更清楚整個流程。

Java代碼
  1. public class HelloWorld {    
  2.     
  3.     public int foo(int i, int j){    
  4.         int k = i + j;    
  5.         return k;    
  6.     }    
  7.     
  8.     public static void main(String[] args) {    
  9.         System.out.print(new HelloWorld().foo(1, 2));    
  10.     }    
  11. }    

深入理解Dalvik虛擬機- 解釋器的運行機制

  Dalvik虛擬機有兩個棧,一個Java棧,一個是VM的native棧,vm的棧是OS的函數調用棧,Java的棧則是由VM管理的棧,每次在dvmCallMethod的時候,在Method執行之前,會調用dvmPushInterpFrame(java→java)或者dvmPushJNIFrame(java→native),JNI的Frame比InterpFrame少了局部變量的棧空間,native函數的局部變量是在vm的native棧裡,由OS負責壓棧出棧。DvmCallMethod結束的時候會調用dvmPopFrame做Java Stack的出棧。

  所以Java Method的執行就是dvmInterpret函數對這個Method的字節碼做解析,函數的實參與局部變量都在Java的Stack裡獲取。SaveBlock是StackSaveArea數據結構,裡面包含了當前函數對應的棧信息,包括返回地址等。而Native  Method的執行就是Method的nativeFunc的執行,實參和局部變量都是在VM的native stack裡。

  Method的nativeFunc是native函數的入口,dalvik虛擬機上的java 的函數hook技術,都是通過改變Method的屬性,SET_METHOD_FLAG(method, ACC_NATIVE),偽裝成native函數,再設置nativeFunc作為鉤子函數,從而實現hook功能。很顯然,hook了的method不再具有多態性。

  nativeFunc的默認函數是dvmResolveNativeMethod(vm/Native.cpp)

C++代碼
  1. void dvmResolveNativeMethod(const u4* args, JValue* pResult,    
  2.     const Method* method, Thread* self)    
  3. {    
  4.     ClassObject* clazz = method->clazz;    
  5.     
  6.     /*  
  7.      * If this is a static method, it could be called before the class  
  8.      * has been initialized.  
  9.      */    
  10.     if (dvmIsStaticMethod(method)) {    
  11.         if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {    
  12.             assert(dvmCheckException(dvmThreadSelf()));    
  13.             return;    
  14.         }    
  15.     } else {    
  16.         assert(dvmIsClassInitialized(clazz) ||    
  17.                dvmIsClassInitializing(clazz));    
  18.     }    
  19.     
  20.     /* start with our internal-native methods */    
  21.     DalvikNativeFunc infunc = dvmLookupInternalNativeMethod(method);    
  22.     if (infunc != NULL) {    
  23.         /* resolution always gets the same answer, so no race here */    
  24.         IF_LOGVV() {    
  25.             char* desc = dexProtoCopyMethodDescriptor(&method->prototype);    
  26.             LOGVV("+++ resolved native %s.%s %s, invoking",    
  27.                 clazz->descriptor, method->name, desc);    
  28.             free(desc);    
  29.         }    
  30.         if (dvmIsSynchronizedMethod(method)) {    
  31.             ALOGE("ERROR: internal-native can't be declared 'synchronized'");    
  32.             ALOGE("Failing on %s.%s", method->clazz->descriptor, method->name);    
  33.             dvmAbort();     // harsh, but this is VM-internal problem    
  34.         }    
  35.         DalvikBridgeFunc dfunc = (DalvikBridgeFunc) infunc;    
  36.         dvmSetNativeFunc((Method*) method, dfunc, NULL);    
  37.         dfunc(args, pResult, method, self);    
  38.         return;    
  39.     }    
  40.     
  41.     /* now scan any DLLs we have loaded for JNI signatures */    
  42.     void* func = lookupSharedLibMethod(method);    
  43.     if (func != NULL) {    
  44.         /* found it, point it at the JNI bridge and then call it */    
  45.         dvmUseJNIBridge((Method*) method, func);    
  46.         (*method->nativeFunc)(args, pResult, method, self);    
  47.         return;    
  48.     }    
  49.     
  50.     IF_ALOGW() {    
  51.         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);    
  52.         ALOGW("No implementation found for native %s.%s:%s",    
  53.             clazz->descriptor, method->name, desc);    
  54.         free(desc);    
  55.     }    
  56.     
  57.     dvmThrowUnsatisfiedLinkError("Native method not found", method);    
  58. }

  dvmResolveNativeMethod首先會調用dvmLookupInternalNativeMethod查詢這個函數是否預置的函數,主要是查下面的函數集:

C++代碼
  1. static DalvikNativeClass gDvmNativeMethodSet[] = {    
  2.     { "Ljava/lang/Object;",               dvm_java_lang_Object, 0 },    
  3.     { "Ljava/lang/Class;",                dvm_java_lang_Class, 0 },    
  4.     { "Ljava/lang/Double;",               dvm_java_lang_Double, 0 },    
  5.     { "Ljava/lang/Float;",                dvm_java_lang_Float, 0 },    
  6.     { "Ljava/lang/Math;",                 dvm_java_lang_Math, 0 },    
  7.     { "Ljava/lang/Runtime;",              dvm_java_lang_Runtime, 0 },    
  8.     { "Ljava/lang/String;",               dvm_java_lang_String, 0 },    
  9.     { "Ljava/lang/System;",               dvm_java_lang_System, 0 },    
  10.     { "Ljava/lang/Throwable;",            dvm_java_lang_Throwable, 0 },    
  11.     { "Ljava/lang/VMClassLoader;",        dvm_java_lang_VMClassLoader, 0 },    
  12.     { "Ljava/lang/VMThread;",             dvm_java_lang_VMThread, 0 },    
  13.     { "Ljava/lang/reflect/AccessibleObject;",    
  14.             dvm_java_lang_reflect_AccessibleObject, 0 },    
  15.     { "Ljava/lang/reflect/Array;",        dvm_java_lang_reflect_Array, 0 },    
  16.     { "Ljava/lang/reflect/Constructor;",    
  17.             dvm_java_lang_reflect_Constructor, 0 },    
  18.     { "Ljava/lang/reflect/Field;",        dvm_java_lang_reflect_Field, 0 },    
  19.     { "Ljava/lang/reflect/Method;",       dvm_java_lang_reflect_Method, 0 },    
  20.     { "Ljava/lang/reflect/Proxy;",        dvm_java_lang_reflect_Proxy, 0 },    
  21.     { "Ljava/util/concurrent/atomic/AtomicLong;",    
  22.             dvm_java_util_concurrent_atomic_AtomicLong, 0 },    
  23.     { "Ldalvik/bytecode/OpcodeInfo;",     dvm_dalvik_bytecode_OpcodeInfo, 0 },    
  24.     { "Ldalvik/system/VMDebug;",          dvm_dalvik_system_VMDebug, 0 },    
  25.     { "Ldalvik/system/DexFile;",          dvm_dalvik_system_DexFile, 0 },    
  26.     { "Ldalvik/system/VMRuntime;",        dvm_dalvik_system_VMRuntime, 0 },    
  27.     { "Ldalvik/system/Zygote;",           dvm_dalvik_system_Zygote, 0 },    
  28.     { "Ldalvik/system/VMStack;",          dvm_dalvik_system_VMStack, 0 },    
  29.     { "Lorg/apache/harmony/dalvik/ddmc/DdmServer;",    
  30.             dvm_org_apache_harmony_dalvik_ddmc_DdmServer, 0 },    
  31.     { "Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;",    
  32.             dvm_org_apache_harmony_dalvik_ddmc_DdmVmInternal, 0 },    
  33.     { "Lorg/apache/harmony/dalvik/NativeTestTarget;",    
  34.             dvm_org_apache_harmony_dalvik_NativeTestTarget, 0 },    
  35.     { "Lsun/misc/Unsafe;",                dvm_sun_misc_Unsafe, 0 },    
  36.     { NULL, NULL, 0 },    
  37. };

  不是內置的話,就會加載so庫,查詢對應的native函數,查詢的規則就是我們熟知的了,com.xx.Helloworld.foobar對應com_xx_Helloworld_foobar。要注意的是,這個函數並不是nativeFunc,接下來的dvmUseJNIBridge調用裡,dvmCallJNIMethod會作為nativeFunc,這個函數主要需要將之前提到的java stack frame裡的ins實參,轉譯成jni的函數調用參數。xposed/dexposed就會自己設置自己的nativeFun自己接管native函數的執行。

  dvmInterpret是解釋器的代碼入口,代碼位置在interp/Interp.cpp

C++代碼
  1. void dvmInterpret(Thread* self, const Method* method, JValue* pResult)    
  2. {    
  3.     InterpSaveState interpSaveState;    
  4.     ExecutionSubModes savedSubModes;    
  5.     . . .     
  6.     interpSaveState = self->interpSave;    
  7.     self->interpSave.prev = &interpSaveState;     
  8.     . . .     
  9.     
  10.     self->interpSave.method = method;    
  11.     self->interpSave.curFrame = (u4*) self->interpSave.curFrame;    
  12.     self->interpSave.pc = method->insns;    
  13.     . . .    
  14.     typedef void (*Interpreter)(Thread*);    
  15.     Interpreter stdInterp;    
  16.     if (gDvm.executionMode == kExecutionModeInterpFast)    
  17.         stdInterp = dvmMterpStd;    
  18. #if defined(WITH_JIT)    
  19.     else if (gDvm.executionMode == kExecutionModeJit ||    
  20.              gDvm.executionMode == kExecutionModeNcgO0 ||    
  21.              gDvm.executionMode == kExecutionModeNcgO1)    
  22.         stdInterp = dvmMterpStd;    
  23. #endif    
  24.     else    
  25.         stdInterp = dvmInterpretPortable;    
  26.     
  27.     // Call the interpreter    
  28.     (*stdInterp)(self);    
  29.     *pResult = self->interpSave.retval;    
  30.     
  31.     /* Restore interpreter state from previous activation */    
  32.     self->interpSave = interpSaveState;    
  33. #if defined(WITH_JIT)    
  34.     dvmJitCalleeRestore(calleeSave);    
  35. #endif    
  36.     if (savedSubModes != kSubModeNormal) {    
  37.         dvmEnableSubMode(self, savedSubModes);    
  38.     }    
  39. }

  Thread的一個很重要的field就是interpSave,是InterpSaveState類型的,裡面包含了當前函數,pc,當前棧幀等重要的變量,dvmInterpret一開始調用的時候就會初始化。

  Dalvik解釋器有兩個,一個是dvmInterpretPortable,一個是 dvmMterpStd。兩者的區別在於,前者是從c++實現,後者是匯編實現。

  dvmInterpretPortable是在vm/mterp/out/InterpC-portable.cpp中定義

C++代碼
  1. void dvmInterpretPortable(Thread* self)    
  2. {    
  3.     . . .    
  4.     DvmDex* methodClassDex;     // curMethod->clazz->pDvmDex    
  5.     JValue retval;    
  6.     
  7.     /* core state */    
  8.     const Method* curMethod;    // method we're interpreting    
  9.     const u2* pc;               // program counter    
  10.     u4* fp;                     // frame pointer    
  11.     u2 inst;                    // current instruction    
  12.     /* instruction decoding */    
  13.     u4 ref;                     // 16 or 32-bit quantity fetched directly    
  14.     u2 vsrc1, vsrc2, vdst;      // usually used for register indexes    
  15.     /* method call setup */    
  16.     const Method* methodToCall;    
  17.     bool methodCallRange;    
  18.     
  19.     /* static computed goto table */    
  20.     DEFINE_GOTO_TABLE(handlerTable);    
  21.     /* copy state in */    
  22.     curMethod = self->interpSave.method;    
  23.     pc = self->interpSave.pc;    
  24.     fp = self->interpSave.curFrame;    
  25.     retval = self->interpSave.retval;       
  26.     
  27.     methodClassDex = curMethod->clazz->pDvmDex;    
  28.     
  29.     . . .     
  30.        
  31.     FINISH(0);                  /* fetch and execute first instruction */    
  32. /*--- start of opcodes ---*/    
  33.     
  34. /* File: c/OP_NOP.cpp */    
  35. HANDLE_OPCODE(OP_NOP)    
  36.     FINISH(1);    
  37. OP_END    
  38.     
  39. /* File: c/OP_MOVE.cpp */    
  40. HANDLE_OPCODE(OP_MOVE /*vA, vB*/)    
  41.     vdst = INST_A(inst);    
  42.     vsrc1 = INST_B(inst);    
  43.     ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",    
  44.         (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,    
  45.         kSpacing, vdst, GET_REGISTER(vsrc1));    
  46.     SET_REGISTER(vdst, GET_REGISTER(vsrc1));    
  47.     FINISH(1);    
  48. OP_END    
  49. …..    
  50. }

  解釋器的指令執行是通過跳轉表來實現,DEFINE_GOTO_TABLE(handlerTable)定義了指令Op的goto表。

  FINISH(0),則表示從第一條指令開始執行,

C++代碼
  1. # define FINISH(_offset) {                                                  \    
  2.         ADJUST_PC(_offset);                                                 \    
  3.         inst = FETCH(0);                                                    \    
  4.         if (self->interpBreak.ctl.subMode) {                                \    
  5.             dvmCheckBefore(pc, fp, self);                                   \    
  6.         }                                                                   \    
  7.         goto *handlerTable[INST_INST(inst)];                                \    
  8.     }    
  9.     
  10. #define FETCH(_offset)     (pc[(_offset)])  

  FETCH(0)獲得當前要執行的指令,通過查跳轉表handlerTable來跳轉到這條指令的執行點,就是函數後面的HANDLE_OPCODE的定義。

  後者是針對不同平台做過優化的解釋器。

  dvmMterpStd會做匯編級的優化,dvmMterpStdRun的入口就是針對不同的平台指令集,有對應的解釋器代碼,比如armv7 neon對應的代碼就在mterp/out/InterpAsm-armv7-a-neon.S。

C++代碼
  1. dvmMterpStdRun:    
  2. #define MTERP_ENTRY1 \    
  3.     .save {r4-r10,fp,lr}; \    
  4.     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs    
  5. #define MTERP_ENTRY2 \    
  6.     .pad    #4; \    
  7.     sub     sp, sp, #4                  @ align 64    
  8.     
  9.     .fnstart    
  10.     MTERP_ENTRY1    
  11.     MTERP_ENTRY2    
  12.     
  13.     /* save stack pointer, add magic word for debuggerd */    
  14.     str     sp, [r0, #offThread_bailPtr]  @ save SP for eventual return    
  15.     
  16.     /* set up "named" registers, figure out entry point */    
  17.     mov     rSELF, r0                   @ set rSELF    
  18.     LOAD_PC_FP_FROM_SELF()              @ load rPC and rFP from "thread"    
  19.     ldr     rIBASE, [rSELF, #offThread_curHandlerTable] @ set rIBASE    
  20.     . . .    
  21.     /* start executing the instruction at rPC */    
  22.     FETCH_INST()                        @ load rINST from rPC    
  23.     GET_INST_OPCODE(ip)                 @ extract opcode from rINST    
  24.     GOTO_OPCODE(ip)                     @ jump to next instruction    
  25.     . . .    
  26.     
  27. #define rPC     r4    
  28. #define rFP     r5    
  29. #define rSELF   r6    
  30. #define rINST   r7    
  31. #define rIBASE  r8    

  非jit的情況下,先是FETCH_INST把pc的指令加載到rINST寄存器,之後GET_INST_OPCODE獲得操作碼 and     _reg, rINST, #255,是把rINST的低16位給ip寄存器,GOTO_OPCODE跳轉到對應的地址。

  #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6

  rIBASE 指向的curHandlerTable是跳轉表的首地址,GOTO_OPCODE(ip)就將pc的地址指向該指令對應的操作碼所在的跳轉表地址。

C++代碼
  1. static Thread* allocThread(int interpStackSize)    
  2. #ifndef DVM_NO_ASM_INTERP    
  3.     thread->mainHandlerTable = dvmAsmInstructionStart;    
  4.     thread->altHandlerTable = dvmAsmAltInstructionStart;    
  5.     thread->interpBreak.ctl.curHandlerTable = thread->mainHandlerTable;    
  6. #endif    

  可見dvmAsmInstructionStart就是跳轉表的入口,定義在dvmMterpStdRun裡,

  你可以在這裡找到所有的Java字節碼的指令對應的解釋器代碼。

  比如new操作符對應的代碼如下,先加載Thread.interpSave.methodClassDex,這是一個DvmDex指針,隨後加載 DvmDex的pResClasses來查找類是否加載過,如果沒加載過,那麼跳轉到 LOP_NEW_INSTANCE_resolve去加載類,如果加載過,就是類的初始化以及AllocObject的處理。LOP_NEW_INSTANCE_resolve就是調用clazz的dvmResolveClass加載。

C++代碼
  1. /* ------------------------------ */    
  2.     .balign 64    
  3. .L_OP_NEW_INSTANCE: /* 0x22 */    
  4. /* File: armv5te/OP_NEW_INSTANCE.S */    
  5.     /*  
  6.      * Create a new instance of a class.  
  7.      */    
  8.     /* new-instance vAA, class@BBBB */    
  9.     ldr     r3, [rSELF, #offThread_methodClassDex]    @ r3<- pDvmDex    
  10.     FETCH(r1, 1)                        @ r1<- BBBB    
  11.     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses    
  12.     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class    
  13. #if defined(WITH_JIT)    
  14.     add     r10, r3, r1, lsl #2         @ r10<- &resolved_class    
  15. #endif    
  16.     EXPORT_PC()                         @ req'd for init, resolve, alloc    
  17.     cmp     r0, #0                      @ already resolved?    
  18.     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now    
  19. .LOP_NEW_INSTANCE_resolved:   @ r0=class    
  20.     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum    
  21.     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?    
  22.     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now    
  23. .LOP_NEW_INSTANCE_initialized: @ r0=class    
  24.     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call    
  25.     bl      dvmAllocObject              @ r0<- new object    
  26.     b       .LOP_NEW_INSTANCE_finish          @ continue    
  27.     
  28.     
  29. .LOP_NEW_INSTANCE_needinit:    
  30.     mov     r9, r0                      @ save r0    
  31.     bl      dvmInitClass                @ initialize class    
  32.     cmp     r0, #0                      @ check boolean result    
  33.     mov     r0, r9                      @ restore r0    
  34.     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue    
  35.     b       common_exceptionThrown      @ failed, deal with init exception    
  36.     
  37.     /*  
  38.      * Resolution required.  This is the least-likely path.  
  39.      *  
  40.      *  r1 holds BBBB  
  41.      */    
  42. .LOP_NEW_INSTANCE_resolve:    
  43.     ldr     r3, [rSELF, #offThread_method] @ r3<- self->method    
  44.     mov     r2, #0                      @ r2<- false    
  45.     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz    
  46.     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr    
  47.     cmp     r0, #0                      @ got null?    
  48.     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue    
  49.     b       common_exceptionThrown      @ yes, handle exception  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved