从Hotspot对象实例化过程,理解类加载
Java 对象的实例化JVM都做了那些事情?在日常编写Java项目的时候,实例化过无数多的对象,随时都在与JVM交互!对JVM的认识总是停留在只是知道它能解析识别,并加载运行Java编写的程序,好奇心驱使着我开始关注JVM是如何实现这一系列功能的。
即使读过《深入理解Java虚拟机》,对JVM的理解也只是达到一个入门的程度,开源的JVM实现凤毛菱角,为大家所熟知的OpenJDK自然成为了想一探究竟的入口,经过一番的搜寻,发现另外一本《Hotspot实战》让我看到了一丝希望。这本书买过来在我的书桌有一段时间了,最近终于有空仔细阅读了前面三章的内容,但纸上得来终觉浅,源码面前无秘密,跟着这本书终于满足我对JVM的一丝好奇心。
面对Hotspot如此庞大的工程,并且C++语言对大多数人也不太熟悉,项目的入口在哪里?这个我目前也不太清楚;我最关心的是什么?main、Launcher、new关键字大概是我最想了解的,类加载恰好可以串联它们。第一篇JVM相关的博客,看书和写博客都是都是慢长的过程(个人感觉),有些东西不值得看,也不值得写,JVM属于另外一类,那就抽空看,再慢慢写。
类加载
一个class文件,需要依次完成加载、链接、初始化三个阶段,才可以在JVM中正常的使用。如创建实例,访问类的静态方法和域。
主要步骤如下:
1 class 文件加载完成hook,提供parse前改变字节码的能力
2 读取魔数、大版本和小版本号、类的常量池(符号引用)、访问标示
3 解析类的接口、域、方法及父类
4 计算vtable 和 itable 大小
5 创建InstanceKlass
6 创建Java 镜像类,并初始化静态成员变量
1 | instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, |
类的实例化
从虚拟机层面来看,所有的Java构造函数都显示为具有特殊名称 <init> 的实例初始化方法。Hotspot中调用<init>的代码如下:
vmSymbols.h 头文件包含object_initializer_name:
1 |
|
jvm.cpp
JVM_AllocateNewObject(JNIEnv *env,
jobject receiver,
jclass currClass,
jclass initClass){
......
methodHandle m(THREAD,init_klass->find_method(vmSymbols::object_initializer_name(),vmSymbols::void_method_signature()));
Handle obj = curr_klass->allocate_instance_handle(CHECK_NULL);
// Call constructor m. This might call a constructor higher up in the hierachy
JavaCalls::call_default_constructor(thread, m, obj, CHECK_NULL);
}
待续…
追问
Java如何实现重载以及重写的?
一个对象最少占用多大的内存?