首先简要介绍一下class文件的结构(详细内容请参考Java虚拟机规范,在《深入Java虚拟机》一书中也有详细描述):
文件系统中的一个class文件,要想成为能在虚拟上运行的Java程序的一部分,必须经过“装载->连接->初始化”三个步骤。其中装载是最基础的一步,它的作用是读取class文件的信息,并生成对象。下面介绍一下KVM中与类加载相关的内容是如何实现的。
长度(字节) |
名称 |
解释 |
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
|
属性信息表 |
数据结构:
在头文件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结构中的。
分享到:
相关推荐
安装完成后,可以通过检查模块是否被正确加载来验证安装是否成功: ``` lsmod | grep kvm ``` 如果看到输出了与KVM相关的模块信息,则表示安装成功。 4. **创建虚拟磁盘文件** 使用`qemu-img`工具创建虚拟...
KVM模块可以作为内核的一部分直接编译进去,也可以作为一个可加载的模块动态加载到内核中。KVM模块为虚拟机提供了底层的支持,而QEMU则在用户空间中提供了高级的功能和服务。 #### 二、KVM的工作流程 KVM的工作...
**四、KVM类的加载** KVM类是用于管理KVM虚拟机的C语言API,主要包含在`<linux/kvm.h>`头文件中。使用这些API,你可以创建、配置和管理虚拟机。例如,创建一个新的虚拟机实例,需要打开KVM设备,分配内存,设置CPU和...
如果执行指令后有类似返回,则证明 KVM 模块加载正常,否则检查 BIOS 中是否开启了 CPU VT 支持。 4. 安装 virtsh virt-install 管理工具 使用以下命令安装 virtsh virt-install 管理工具: `yum install libvirt...
在KVM启动时,内核加载KVM模块并通过执行VMXON指令进入VMX操作模式,此时VMM处于VMX Root模式。当Guest OS执行特权或敏感指令时,会触发VM Exit事件,此时系统挂起Guest OS,并通过VMCALL调用VMM切换到Root模式执行...
KVM架构的工作原理是通过加载KVM内核模块,将Linux内核转换为一个系统管理程序,然后使用QEMU模拟器来模拟硬件环境,最后使用libvirt管理工具来管理虚拟机。这种架构可以提供一个高效、可靠的虚拟化环境,同时也可以...
- 加载KVM内核模块:通过命令 `modprobe kvm` 或者 `modprobe kvm_intel` 或 `modprobe kvm_amd` 来加载。 - 安装KVM软件包:根据使用的Linux发行版,可以通过相应的包管理器来安装KVM及相关工具。 3. **安装QEMU...
然后,使用 virsh attach-device 命令将 XML 文件加载到虚拟机中。 ``` [root@kvm11 ~]# virsh attach-device web37 web37add02.xml --persistent ``` 2. attach-disk 方式 首先,需要创建一个 qcow2 格式的磁盘...
- **检查内核模块**:确保内核已加载 kvm 模块。在 Ubuntu 系统中,默认情况下这些模块通常是激活的。 - **安装 qemu-kvm**:可以通过包管理器安装 qemu-kvm,如使用 apt-get 或 yum。 - **安装 libvirt**:同样,...
KVM(Kernel-based Virtual Machine)是Linux内核中的一个模块,它允许你在Linux系统上运行多个虚拟机。在KVM环境中安装Windows操作系统时,为了确保最佳的性能和兼容性,通常需要安装特定的驱动程序。这些驱动主要...
- **函数`kvm_run()`**:调度vCPU执行,通过`ioctl(KVM_RUN)`将vCPU状态加载到物理处理器并开始执行。 了解这些关键函数和流程对于深入理解KVM的工作原理至关重要,这有助于开发者调试和优化KVM虚拟化环境,以实现...
如果你的 CPU 是 Intel 的,可以加载 kvm-intel 内核: ``` [root@target ~]# modprobe kvm-intel ``` 如果你的 CPU 是 AMD 的,可以加载 kvm-amd 内核: ``` [root@target ~]# modprobe kvm-amd ``` 我们可以使用...
如果Guest OS 发生外部中断或者影子页表缺页之类的情况,会暂停Guest OS的执行,退出客户模式,执行异常处理,之后重新进入客户模式,执行客户代码。 二、Qemu原理介绍 Qemu是一个纯软件实现的虚拟化模拟器,能够...
将ISO文件加载到KVM虚拟机的CD/DVD驱动器中,这通常可以通过KVM客户端的图形界面完成。 4. 创建虚拟机:在KVM客户端中,创建一个新的虚拟机实例。定义所需的硬件配置,如内存大小、CPU数量以及磁盘空间等。 5. ...
2. 检查 KVM 相关模块和 tun 模块的加载情况:使用“lsmod”命令可以查看 KVM 相关模块和 tun 模块是否已经加载,使用“modprobe tun”命令可以加载 tun 模块。 3. 检查 /dev/net/tun 的权限:/dev/net/tun 是一个...
为了使虚拟化环境能够在启动时被正确识别和加载,还需要对启动菜单进行相应的配置。具体步骤如下: 1. **对于PMON类型的固件**:在`/boot/boot.cfg`文件中的`showmenu1`行下添加启动项: ```plaintext title '...
KVM 是 Linux 的一个模块,可以使用 modprobe 加载 KVM 模块,但仅有 KVM 模块是不够的,因为用户无法直接控制内核模块去做事情,还需要一个用户空间的工具来控制 KVM。 KVM 使用 QEMU 作为用户空间的工具,QEMU 是...