KVM的类加载
2007-12-23 12:22:13 来源:WEB开发网首先简要介绍一下class文件的结构(详细内容请参考java虚拟机规范,在《深入Java虚拟机》一书中也有详细描述):
长度(字节)
名称
解释
4
magic
0xCAFEBABE,Java文件的标识,常称为“魔数”
2
minor_version
次版本号
2
major_version
主版本号
2
constant_pool_count
常量池中项目个数
(constant_pool_count-1)*cp_item
constant_pool
常量池,其中存放了(constant_pool_count-1)个常量池项
2
access_flags
本class的类型信息
2
this_class
本class的全限定名的常量池项索引
2
super_class
超类的全限定名的常量池项索引
2
interfaces_count
实现/扩展的接口数
2*interfaces_count
interfaces
实现/扩展的接口名的常量池项索引
2
fields_count
字段数
fields_count* cp_item
fields
字段信息表
2
methods_count
方法数
methods_count* cp_item
methods
方法信息表
2
attributes_count
属性数
attributes_count* cp_item
attributes
属性信息表
文件系统中的一个class文件,要想成为能在虚拟上运行的Java程序的一部分,必须经过“装载->连接->初始化”三个步骤。其中装载是最基础的一步,它的作用是读取class文件的信息,并生成对象。下面介绍一下KVM中与类加载相关的内容是如何实现的。
数据结构:
在头文件kvm/vmcommon/h/class.h中定义有两个非常重要的结构体:
strUCt classStruct {
COMMON_OBJECT_INFO(INSTANCE_CLASS)
UString packageName; /* Everything before the final '/' */
UString baseName; /* Everything after the final '/' */
CLASS next; /* Next item in this hash table bucket */
unsigned short accessFlags; /* Access information */
unsigned short key; /* Class key */
};
typedef struct classStruct* CLASS;
/* INSTANCE_CLASS */
struct instanceClassStruct {
struct classStruct clazz; /* common info */
/* And specific to instance classes */
INSTANCE_CLASS superClass; /* Superclass, unless java.lang.Object */
CONSTANTPOOL constPool; /* Pointer to constant pool */
FIELDTABLE fieldTable; /* Pointer to instance variable table */
METHODTABLE methodTable; /* Pointer to virtual method table */
unsigned short* ifaceTable; /* Pointer to interface table */
POINTERLIST staticFields; /* Holds static fields of the class */
short instSize; /* The size of class instances */
short status; /* Class readiness status */
THREAD initThread; /* Thread performing class initialization */
NativeFuncPtr finalizer; /* Pointer to finalizer */
};
typedef struct instanceClassStruct* INSTANCE_CLASS;
classStruct与instanceClassStruct这两个结构体都是与class(可能包括类和接口)有关的,但不所不同。classStruct所提供是一些“外围信息”,包括全限定名和可见性等,是一个class区分其它class的基本信息;instanceClassStruct所提供的是一些“内容信息”,是一个类本身所定义的内容,比如方法表、字段表等等。
程序实现:
下面来看一看在KVM中instanceClassStruct的信息是如何读取的。
一个kvm虚拟机在运行时,class来自于两种来源:一是系统类库,这些类来自KVM本身;二是用户程序,来自文件系统。下面分别介绍:
1、前文提到过,对于系统类库,KVM会先把class文件转化为C语言源代码,然后编入kvm可执行程序中,这样当使用系统类库时,kvm就不再访问外部,这一步骤叫可暂称为ROM,ROM过程中所做的事情之一就是生成所有系统类库中class的INSTANCE_CLASS,也就是说,这些类的信息早在ROM的过程中就已准备好,使用时只要读入即可。
ROM生成的INSTANCE_CLASS信息存放在源文件tools/jcc/ROMjavaUnix.c的static struct AllClassblocks_Struct AllClassblocks结构中,使用这一结构的代码也在同一文件中,比如:
(INSTANCE_CLASS)&AllClassblocks.java_lang_String;
这里就生成了String类对应的INSTANCE_CLASS结构。
2、对于用户定义的类,INSTANCE_CLASS信息就要从文件系统中获得。
获得类信息的主要入口函数是
void loadClassfile(INSTANCE_CLASS InitiatingClass, bool_t fatalErrorIfFail);
在文件kvm/vmcommon/src/loader.c中。其中参数InitiatingClass就是一个空的INSTANCE_CLASS结构体,在loadClassfile函数中,InitiatingClass的内容将被逐步填充。
在loadClassfile中,将调用另一个重要的函数:
static void loadRawClass(INSTANCE_CLASS CurrentClass, bool_t fatalErrorIfFail);
在这个函数中,将调用下列各方法分别载入class文件中的各种信息:
函数名(参数及返回值省略)
功能
loadVersionInfo()
载入版本号
loadConstantPool()
载入常量池
loadClassInfo()
载入类型信息
loadInterfaces()
载入所实现的接口
loadFields()
载入字段表
loadMethods()
载入方法表
ignoreAttributes()
载入扩展的属性表
上表中的每一个函数都会带有一个FILEPOINTER_HANDLE型的参数,它是一个文件的句柄,这些函数就是从这个文件中顺序读取各种信息并存入INSTANCE_CLASS结构中的。
首先简要介绍一下class文件的结构(详细内容请参考Java虚拟机规范,在《深入Java虚拟机》一书中也有详细描述):
长度(字节)
名称
解释
4
magic
0xCAFEBABE,Java文件的标识,常称为“魔数”
2
minor_version
次版本号
2
major_version
主版本号
2
constant_pool_count
常量池中项目个数
(constant_pool_count-1)*cp_item
constant_pool
常量池,其中存放了(constant_pool_count-1)个常量池项
2
access_flags
本class的类型信息
2
this_class
本class的全限定名的常量池项索引
2
super_class
超类的全限定名的常量池项索引
2
interfaces_count
实现/扩展的接口数
2*interfaces_count
interfaces
实现/扩展的接口名的常量池项索引
2
fields_count
字段数
fields_count* cp_item
fields
字段信息表
2
methods_count
方法数
methods_count* cp_item
methods
方法信息表
2
attributes_count
属性数
attributes_count* cp_item
attributes
属性信息表
文件系统中的一个class文件,要想成为能在虚拟上运行的Java程序的一部分,必须经过“装载->连接->初始化”三个步骤。其中装载是最基础的一步,它的作用是读取class文件的信息,并生成对象。下面介绍一下KVM中与类加载相关的内容是如何实现的。
数据结构:
在头文件kvm/vmcommon/h/class.h中定义有两个非常重要的结构体:
struct classStruct {
COMMON_OBJECT_INFO(INSTANCE_CLASS)
UString packageName; /* Everything before the final '/' */
UString baseName; /* Everything after the final '/' */
CLASS next; /* Next item in this hash table bucket */
unsigned short accessFlags; /* Access information */
unsigned short key; /* Class key */
};
typedef struct classStruct* CLASS;
/* INSTANCE_CLASS */
struct instanceClassStruct {
struct classStruct clazz; /* common info */
/* And specific to instance classes */
INSTANCE_CLASS superClass; /* Superclass, unless java.lang.Object */
CONSTANTPOOL constPool; /* Pointer to constant pool */
FIELDTABLE fieldTable; /* Pointer to instance variable table */
METHODTABLE methodTable; /* Pointer to virtual method table */
unsigned short* ifaceTable; /* Pointer to interface table */
POINTERLIST staticFields; /* Holds static fields of the class */
short instSize; /* The size of class instances */
short status; /* Class readiness status */
THREAD initThread; /* Thread performing class initialization */
NativeFuncPtr finalizer; /* Pointer to finalizer */
};
typedef struct instanceClassStruct* INSTANCE_CLASS;
classStruct与instanceClassStruct这两个结构体都是与class(可能包括类和接口)有关的,但不所不同。classStruct所提供是一些“外围信息”,包括全限定名和可见性等,是一个class区分其它class的基本信息;instanceClassStruct所提供的是一些“内容信息”,是一个类本身所定义的内容,比如方法表、字段表等等。
程序实现:
下面来看一看在KVM中instanceClassStruct的信息是如何读取的。
一个kvm虚拟机在运行时,class来自于两种来源:一是系统类库,这些类来自KVM本身;二是用户程序,来自文件系统。下面分别介绍:
1、前文提到过,对于系统类库,KVM会先把class文件转化为C语言源代码,然后编入kvm可执行程序中,这样当使用系统类库时,kvm就不再访问外部,这一步骤叫可暂称为ROM,ROM过程中所做的事情之一就是生成所有系统类库中class的INSTANCE_CLASS,也就是说,这些类的信息早在ROM的过程中就已准备好,使用时只要读入即可。
ROM生成的INSTANCE_CLASS信息存放在源文件tools/jcc/ROMjavaUnix.c的static struct AllClassblocks_Struct AllClassblocks结构中,使用这一结构的代码也在同一文件中,比如:
(INSTANCE_CLASS)&AllClassblocks.java_lang_String;
这里就生成了String类对应的INSTANCE_CLASS结构。
2、对于用户定义的类,INSTANCE_CLASS信息就要从文件系统中获得。
获得类信息的主要入口函数是
void loadClassfile(INSTANCE_CLASS InitiatingClass, bool_t fatalErrorIfFail);
在文件kvm/vmcommon/src/loader.c中。其中参数InitiatingClass就是一个空的INSTANCE_CLASS结构体,在loadClassfile函数中,InitiatingClass的内容将被逐步填充。
在loadClassfile中,将调用另一个重要的函数:
static void loadRawClass(INSTANCE_CLASS CurrentClass, bool_t fatalErrorIfFail);
在这个函数中,将调用下列各方法分别载入class文件中的各种信息:
函数名(参数及返回值省略)
功能
loadVersionInfo()
载入版本号
loadConstantPool()
载入常量池
loadClassInfo()
载入类型信息
loadInterfaces()
载入所实现的接口
loadFields()
载入字段表
loadMethods()
载入方法表
ignoreAttributes()
载入扩展的属性表
上表中的每一个函数都会带有一个FILEPOINTER_HANDLE型的参数,它是一个文件的句柄,这些函数就是从这个文件中顺序读取各种信息并存入INSTANCE_CLASS结构中的。
(出处:http://www.cncms.com)
更多精彩
赞助商链接