赞
踩
加载:根据类的全限定名找到二进制字节流(.class),将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在堆中生成一个代表这个类的class对象,作为方法区中这些数据的访问入口;
验证:验证的主要作用就是确保加载的类的正确性,检验不能对jvm有危害,主要扽为四个阶段的验证:1.文件格式的验证,2.元数据验证,3.字节码验证,4.符号引用验证;
准备:准备阶段主要是为类变量分配内存并设置初始值,这些内存都在方法去分配,这个阶段主要就是两点关键字:类变量,初始值;类变量会分配内存,实例变量不会,实例变量是随着对象的实例化一块分配到堆中;初始值指的是数据类型默认值,而不是代码中被显示赋予的值;
解析:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段,方法在内存中的指针或者偏移量。
初始化:在初始化阶段,主要为类的静态变量赋予正确的初始值,jvm负责对类进行初始化,主要对类变量进行初始化,一句话描述就是这个阶段就是执行类构造器clinit方法的过程。
jvm中内置了三个重要的classLoader,除了bootstrapClassLoader,其他的类加载器均由java实现且全部继承自java.lang.classLoader。
bootstrapClassLoader启动类加载器:最顶层的加载类
extensionClassLoader扩展类加载器;
appClassLoader应用程序类加载器
双亲委派模型:当一个类加载器收到加载任务,会优先交给其父类加载器去完成,因此最终的加载任务都会传递到顶层的启动类加载器,只有父类加载器无法完成加载任务是,才会尝试执行加载任务。
jvm区分不同类的方式不仅仅是根据类名,相同的类文件被不同的类加载器加载会产生的是两个不同的类,所有双亲委派就有一个好处,如果你要加载类,最终都会委托给顶层的去加载,得到的是同一个对象。
好处:1.可以避免重复加载;2.更加安全,很好的解决了各个类加载器的基础类统一问题,不会随意定义类加载器来加载核心api
类加载检查:jvm收到一条new指令是,首先去检查在常量池中能不能定位到这个类的符号引用,并且检查这个类的符号引用代表的类是否已被加载过,解析,初始化过,必须要先执行相应的类加载过程;
分配内存:在类检查过后,jvm会为新生对象分配内存,内存大小在类加载完成时便可确定,为对象分配空间的任务等于把一块确定大小的内存从java堆中划分出来。分配方式有‘指针碰撞’与空闲列表 两种,而java内存是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
初始化零值:内存分配完毕后,jvm需要将分配到的内存空间都初始化为零值(不包括对象头)
设置对象头:初始化零值后,jvm要对对象惊醒必要的设置,如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的gc分代年龄等信息,这些信息存放在对象头中,另外根据jvm当前的运行状态,如是否启用偏向锁,对象头会有不同的设置方式。
执行init方法
从jvm角度来看,一个新的对象已经产生,但从java程序的视角来看,对象的创建才刚刚开始,方法还没有执行,所有的字段都还是零,所以一般来说,执行new指令后会接着执行方法,根据程序员所需要的参数来初始化赋值。对象完全创建完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。