jvm对象创建以及类的加载

当虚拟机遇到一个new命令时,首先将会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载,解析和初始化过。如果没有就必须先执行类加载过程。

类从被加载到虚拟机到被卸载。生命周期:加载,验证,准备,解析,初始化,使用和卸载。

在什么情况下需要加载类呢?

1.遇到new,getstatic,putstatic或invokestatic指令时。常见场景是使用new关键字实例化对象的时候,读取或设置一个类的静态字段(被final修饰,已在编译期把结果放入常量池的静态字段除外)的时候,一起调用一个类的静态方法的时候。

2.使用java.lang.reflect反射。如果类没有进行过初始化则先初始化。

3.当初始化一个类时,如果其父类还没有初始化,则先触发其父类初始化。

4.当虚拟机启动时,虚拟机需先执行一个指定的之类(public main方法),这个类先初始化。

5.jdk1.7版本的java.lang.invoke.MethodHandle.

在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需内存将会被划分出来。

如果java堆时规整的。所有用过的内存在一边,空闲的内存在另一边。中间放着一个指针,分配内存就只是将指针往空闲方向挪动一个与对象大小相等的距离。这种分配内存的方法,称为指针碰撞。

如果java堆不规整。虚拟机就维持一个列表,记录那些内存是可用的,哪些是不可用的。在分配时,从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。这种方式叫做空闲列表。选择哪种分配方式,由java堆是否规整觉定,而java堆是否规整,又由所采用的垃圾回收器是否带有垃圾压缩整理功能决定。

内存分配完成后,虚拟机要对对象进行必要的设置,如,这个对象是哪个类的实例,如何才能找到类的元信息,对象的哈希吗,对象的GC分代年龄等。这些都在对象头(Object Header)中。

以上工作都完成了,从虚拟机角度看,一个新的对象已经产生,但是java程序的角度看,还要进行init,所有字段还为零。把对象按照程序员的意愿进行初始化,一个真正可用的对象才算产生了。

你可能感兴趣的:(java,jvm)