目录
在分析thread.cpp的create_vm函数中(参考《Hotspot启动和初始化源码解析》)发现JVM通过initialize_class函数来加载Java类,该函数是threap.cpp的一个静态函数,其函数定义如下:
接着为main_thread创建thread_object即Java中的java.lang.Thread对象时使用了create_initial_thread函数,该函数返回了oop,实际是类oopDesc* 的别名,如下图:
在《Java程序员自我修养——内存模型》中探讨过,Java对象在内存中是实例数据和类型数据相分离的,实例数据保存了一个指向类型数据的指针,即OOP(ordinary object pointer),因此猜测这里的Klass就是所谓的类型数据,oopDesc就是具体的实例数据了。
1、类继承结构
在上述代码Klass处按crtl并点击即可进入到定义Klass的头文件kclass.hpp中,该文件的位于hotspot\src\share\vm\oops目录下,选中Klass,点击右键,选择Open Type Hierarchy即可显示该类的继承关系图了,如下:
选择其中某一个类如MetaspaceObj,右键选择Open即可进入定义该父类的头文件alloction.hpp,位于hotspot\src\share\vm\memory下,如下图:
2、MetaspaceObj
该类是作为存放在Metaspace元空间的中类的基类,不能执行delete,否则会出现致命错误,注意该类没有定义虚函数。该类重载了new操作符,主要用于给共享只读的或者共享读写的类分配内存,该类定义了如下方法:
该类定义了一个枚举Type用于表示对象类型,包含以下几种类型:
3、Metadata
Metadata是内部表示类相关元数据的一个基类,注意Metadata定义了多个虚函数,其定义的方法如下:
其中identity_hash()方法返回的实际是该对象的内存地址,如下图:
其中跟stack相关的三个方法是类重定义(class redefinition)期间使用的,跟Java栈帧无关。
4、Klass
一个Klass提供两方面的功能:实现Java语言层面的类和提供多态方法的支持。C++类实例通过保存typeinfo指针实现RTTI,通过vtbl指针实现多态,Hotspot的Oop-Klass模型将这两者整合到Klass中,Java类实例只需保留一个Klass指针即可实现RTTI和多态,能够有效降低指针的内存占用。大致方案是用Oop表示Java实例,主要用于表示实例数据,不提供任何虚函数功能,Oop保存了对应Kclass的指针,所有方法调用通过Klass完成并通过Klass获取类型信息,Klass基于C++的虚函数提供对Java多态的支持。Klass作为父类主要职责是描述了类的继承关系, 其包含的重要属性如下:
_layout_helper:_layout_helper是对象内存布局的一个组合描述符,如果不是InstanceKclass或者ArrayKlass,则该值为0.对InstanceKclass而言,该值表示对象的以字节为单位的内存占用空间,对ArrayKlass而言,该值是一个组合起来的假数字,包含4部分,具体怎么组合和解析由子类实现:
- tag:如果数组元素是对象实例则是0x80,否则是0xC0
- hsz: 数组头元素的字节数
- ebt:数组元素的类型,枚举值BasicType
- esz:数组元素大小,以字节为单位
该值因为被频繁查询,所以放在虚函数表指针的后面。
_super_check_offset:用于快速查找supertype的一个偏移量
_secondary_super_cache:Klass指针,上一次observed secondary supertype
_secondary_supers:Klass指针数组,指向secondary supertype,即类实现的接口对应的Kclass
_primary_supers:Klass指针数组,大小固定为8,指向primary supertypes,即默认继承的类如Object
_name: 类名,如java/lang/String,[Ljava/lang/String
_java_mirror: oopDesc指针,此类对应的java/lang/Class实例,可以据此访问类静态属性
_super:Klass指针,父类
_subklass:Klass指针,子类
_next_sibling:Klass指针,该类的下一个子类
_next_link:Klass指针,ClassLoader加载的下一个Klass
_class_loader_data :ClassLoaderData指针,加载该类的ClassLoader
_modifier_flags: 修改标识,Class.getModifiers使用
_access_flags:获取类的修饰符,如private类访问控制,final,static,abstract ,native等
测试用例如下:
package jvmTest;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
interface interTest{
void show();
}
class Base{
private int a=1;
public void print(){
System.out.println("Base");
}
}
class Base2 extends Base{
public int a;
public Base2(int a) {
this.a = a;
}
public void print(){
System.out.println("Base2");
}
}
class A extends Base2 implements interTest {
public int b;
public A(int a,int b) {
super(a);
this.b=b;
}
@Override
public void show() {
System.out.println("a->"+a+",b="+b);
}
public void print(){
System.out.println("A");
}
}
class B extends A{
private int c;
public B(int a, int b) {
super(a, b);
c=3;
}
@Override
public void show() {
System.out.println("a->"+a+",b="+b+",c="+c);
}
public void print(){
System.out.println("B");
}
}
public class MainTest {
public static void main(String[] args) {
A a=new A(1,2);
a.show();
A[] a2={a,new B(2,3)};
while (true){
try {
System.out.println(getProcessID());
Thread.sleep(600*1000);
} catch (Exception e) {
}
}
}