WEB开发网
开发学院软件开发Java KVM的类加载 阅读

KVM的类加载

 2007-12-23 12:22:13 来源:WEB开发网   
核心提示:首先简要介绍一下class文件的结构(详细内容请参考java虚拟机规范,在《深入Java虚拟机》一书中也有详细描述):长度(字节)名称解释4magic0xCAFEBABE,KVM的类加载,Java文件的标识,常称为“魔数”2minor_version次版本号2major_version主版本号2constant_poo

首先简要介绍一下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中定义有两个非常重要的结构体:

Word-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"> /* CLASS */
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 JavaLangString =
   (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中定义有两个非常重要的结构体:

/* CLASS */
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 JavaLangString =
   (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)


Tags:KVM 加载

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接