java 惰性初始化_DVM 初始化 —— 关于Java类的基础知识

DVM,也就是Dalvik,Android4.4之后,还推出了ART,但没有作为默认虚拟机使用,直到5.0才正式作为默认虚拟机使用。可见,一个好的东西是需要经历一些磨难才能出的来的。

我把Java中的类分成两种:Primitive Type和Class Type,其中,Primitive Type,即我们所说的int、double等,而Class Type,即我们所说的class。而不管是何种Type,它们在虚拟机的实现中,都有自己的Class。Class是一个特殊的类,它不能被用来构造一个对象,只在虚拟机初始化的时候,唯一一次被直接加载。

Java中的每一个类都对应着一个C++的ClassObject,包括了我们所用的int等java原始类型。一个Java类的加载,就是填充这个结构体ClassObject。

虚拟机第一个加载的java类就是Class,以下就是虚拟机没有通过findClass去加载一个类,而是通过直接填充一个ClassObject来定义Class这个类

/*

* Initialize the class Class. This has to be done specially, particularly

* because it is an instance of itself.

*/

ClassObject* clazz = (ClassObject*)

dvmMalloc(classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_NON_MOVING);

if (clazz == NULL) {

return false;

}

DVM_OBJECT_INIT(clazz, clazz);

SET_CLASS_FLAG(clazz, ACC_PUBLIC | ACC_FINAL | CLASS_ISCLASS);

clazz->descriptor = "Ljava/lang/Class;";

gDvm.classJavaLangClass = clazz;

LOGVV("Constructed the class Class.");

Primitive  Type在虚拟机中是被enum出来的

/*

* Enumeration of all the primitive types.

*/

enum PrimitiveType {

PRIM_NOT        = 0,       /* value is a reference type, not a primitive type */

PRIM_VOID       = 1,

PRIM_BOOLEAN    = 2,

PRIM_BYTE       = 3,

PRIM_SHORT      = 4,

PRIM_CHAR       = 5,

PRIM_INT        = 6,

PRIM_LONG       = 7,

PRIM_FLOAT      = 8,

PRIM_DOUBLE     = 9,

};

Primitive  Type不像class type,有一个类所在的路径,它是被规定死了一些对应字母,在JNI编程中,人们又叫它“签名”。

/* (documented in header) */

const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) {

switch (type) {

case PRIM_VOID:    return "V";

case PRIM_BOOLEAN: return "Z";

case PRIM_BYTE:    return "B";

case PRIM_SHORT:   return "S";

case PRIM_CHAR:    return "C";

case PRIM_INT:     return "I";

case PRIM_LONG:    return "J";

case PRIM_FLOAT:   return "F";

case PRIM_DOUBLE:  return "D";

default:           return NULL;

}

return NULL;

}

Class Type都有一个包名+类名的形式,而在被加载时,它们都变成了如"Ljava/lang/Object”;"Ljava/lang/Object;”就是Java类的祖宗Object。以下是虚拟机在初始化时,所加载的一些基础类,它们在Java的Libcore里面定义。

static struct { ClassObject** ref; const char* name; } classes[] = {

/*

* Note: The class Class gets special treatment during initial

* VM startup, so there is no need to list it here.

*/

/* The corest of the core classes */

{ &gDvm.classJavaLangObject, "Ljava/lang/Object;" },

{ &gDvm.exThrowable,         "Ljava/lang/Throwable;" },

/* Slightly less core, but still down there, classes */

{ &gDvm.classJavaLangClassArray,             "[Ljava/lang/Class;" },

{ &gDvm.classJavaLangClassLoader,            "Ljava/lang/ClassLoader;" },

{ &gDvm.classJavaLangObjectArray,            "[Ljava/lang/Object;"},

{ &gDvm.classJavaLangStackTraceElement,      "Ljava/lang/StackTraceElement;" },

{ &gDvm.classJavaLangStackTraceElementArray, "[Ljava/lang/StackTraceElement;" },

{ &gDvm.classJavaLangString,                 "Ljava/lang/String;" },

{ &gDvm.classJavaLangThread,                 "Ljava/lang/Thread;" },

{ &gDvm.classJavaLangThreadGroup,            "Ljava/lang/ThreadGroup;" },

{ &gDvm.classJavaLangVMThread,               "Ljava/lang/VMThread;" },

/* Arrays of primitive types */

{ &gDvm.classArrayBoolean, "[Z" },

{ &gDvm.classArrayByte,    "[B" },

{ &gDvm.classArrayShort,   "[S" },

{ &gDvm.classArrayChar,    "[C" },

{ &gDvm.classArrayInt,     "[I" },

{ &gDvm.classArrayLong,    "[J" },

{ &gDvm.classArrayFloat,   "[F" },

{ &gDvm.classArrayDouble,  "[D" },

/* Exception classes */

{ &gDvm.exAbstractMethodError,             "Ljava/lang/AbstractMethodError;" },

{ &gDvm.exArithmeticException,             "Ljava/lang/ArithmeticException;" },

{ &gDvm.exArrayIndexOutOfBoundsException,  "Ljava/lang/ArrayIndexOutOfBoundsException;" },

{ &gDvm.exArrayStoreException,             "Ljava/lang/ArrayStoreException;" },

{ &gDvm.exClassCastException,              "Ljava/lang/ClassCastException;" },

{ &gDvm.exClassCircularityError,           "Ljava/lang/ClassCircularityError;" },

{ &gDvm.exClassNotFoundException,          "Ljava/lang/ClassNotFoundException;" },

{ &gDvm.exClassFormatError,                "Ljava/lang/ClassFormatError;" },

{ &gDvm.exError,                           "Ljava/lang/Error;" },

{ &gDvm.exExceptionInInitializerError,     "Ljava/lang/ExceptionInInitializerError;" },

{ &gDvm.exFileNotFoundException,           "Ljava/io/FileNotFoundException;" },

{ &gDvm.exIOException,                     "Ljava/io/IOException;" },

{ &gDvm.exIllegalAccessError,              "Ljava/lang/IllegalAccessError;" },

{ &gDvm.exIllegalAccessException,          "Ljava/lang/IllegalAccessException;" },

{ &gDvm.exIllegalArgumentException,        "Ljava/lang/IllegalArgumentException;" },

{ &gDvm.exIllegalMonitorStateException,    "Ljava/lang/IllegalMonitorStateException;" },

{ &gDvm.exIllegalStateException,           "Ljava/lang/IllegalStateException;" },

{ &gDvm.exIllegalThreadStateException,     "Ljava/lang/IllegalThreadStateException;" },

{ &gDvm.exIncompatibleClassChangeError,    "Ljava/lang/IncompatibleClassChangeError;" },

{ &gDvm.exInstantiationError,              "Ljava/lang/InstantiationError;" },

{ &gDvm.exInstantiationException,          "Ljava/lang/InstantiationException;" },

{ &gDvm.exInternalError,                   "Ljava/lang/InternalError;" },

{ &gDvm.exInterruptedException,            "Ljava/lang/InterruptedException;" },

{ &gDvm.exLinkageError,                    "Ljava/lang/LinkageError;" },

{ &gDvm.exNegativeArraySizeException,      "Ljava/lang/NegativeArraySizeException;" },

{ &gDvm.exNoClassDefFoundError,            "Ljava/lang/NoClassDefFoundError;" },

{ &gDvm.exNoSuchFieldError,                "Ljava/lang/NoSuchFieldError;" },

{ &gDvm.exNoSuchFieldException,            "Ljava/lang/NoSuchFieldException;" },

{ &gDvm.exNoSuchMethodError,               "Ljava/lang/NoSuchMethodError;" },

{ &gDvm.exNullPointerException,            "Ljava/lang/NullPointerException;" },

{ &gDvm.exOutOfMemoryError,                "Ljava/lang/OutOfMemoryError;" },

{ &gDvm.exRuntimeException,                "Ljava/lang/RuntimeException;" },

{ &gDvm.exStackOverflowError,              "Ljava/lang/StackOverflowError;" },

{ &gDvm.exStaleDexCacheError,              "Ldalvik/system/StaleDexCacheError;" },

{ &gDvm.exStringIndexOutOfBoundsException, "Ljava/lang/StringIndexOutOfBoundsException;" },

{ &gDvm.exTypeNotPresentException,         "Ljava/lang/TypeNotPresentException;" },

{ &gDvm.exUnsatisfiedLinkError,            "Ljava/lang/UnsatisfiedLinkError;" },

{ &gDvm.exUnsupportedOperationException,   "Ljava/lang/UnsupportedOperationException;" },

{ &gDvm.exVerifyError,                     "Ljava/lang/VerifyError;" },

{ &gDvm.exVirtualMachineError,             "Ljava/lang/VirtualMachineError;" },

/* Other classes */

{ &gDvm.classJavaLangAnnotationAnnotationArray, "[Ljava/lang/annotation/Annotation;" },

{ &gDvm.classJavaLangAnnotationAnnotationArrayArray,

"[[Ljava/lang/annotation/Annotation;" },

{ &gDvm.classJavaLangReflectAccessibleObject,   "Ljava/lang/reflect/AccessibleObject;" },

{ &gDvm.classJavaLangReflectConstructor,        "Ljava/lang/reflect/Constructor;" },

{ &gDvm.classJavaLangReflectConstructorArray,   "[Ljava/lang/reflect/Constructor;" },

{ &gDvm.classJavaLangReflectField,              "Ljava/lang/reflect/Field;" },

{ &gDvm.classJavaLangReflectFieldArray,         "[Ljava/lang/reflect/Field;" },

{ &gDvm.classJavaLangReflectMethod,             "Ljava/lang/reflect/Method;" },

{ &gDvm.classJavaLangReflectMethodArray,        "[Ljava/lang/reflect/Method;"},

{ &gDvm.classJavaLangReflectProxy,              "Ljava/lang/reflect/Proxy;" },

{ &gDvm.classJavaNioReadWriteDirectByteBuffer,  "Ljava/nio/ReadWriteDirectByteBuffer;" },

{ &gDvm.classOrgApacheHarmonyDalvikDdmcChunk,

"Lorg/apache/harmony/dalvik/ddmc/Chunk;" },

{ &gDvm.classOrgApacheHarmonyDalvikDdmcDdmServer,

"Lorg/apache/harmony/dalvik/ddmc/DdmServer;" },

{ &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,

"Lorg/apache/harmony/lang/annotation/AnnotationFactory;" },

{ &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,

"Lorg/apache/harmony/lang/annotation/AnnotationMember;" },

{ &gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray,

"[Lorg/apache/harmony/lang/annotation/AnnotationMember;" },

{ NULL, NULL }

};

上面还只是一个部分罗列,不过您也应该能看到很多熟悉又陌生的“类”了吧。DVM在初始化时,就把这些基础类保存下来了,以便于人们可以用来定义其他的类。那么加载呢?真正的加载,是通过initClassReference()方法初始化的。

static bool initClassReference(ClassObject** pClass, const char* name) {

ClassObject* result;

assert(*pClass == NULL);

if (name[0] == '[') {

result = dvmFindArrayClass(name, NULL);

} else {

result = dvmFindSystemClassNoInit(name);

}

if (result == NULL) {

ALOGE("Could not find essential class %s", name);

return false;

}

*pClass = result;

return true;

}

而initClassReference()方法又是通过dvmFindArrayClass()和dvmFindSystemClassNoInit()来加载的,这里可以简单的把它们都看成findClass()。

findClass(),就是我们所说的一个类的加载,也就是完成结构体ClassObject的填充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值