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的填充。

你可能感兴趣的:(DVM 初始化 —— 关于Java类的基础知识)