简介
在应用层,我们只需要写一个new关键字,就可以创建出一个对象,但实际上虚拟机帮我们做了很多的工作。
1.对象的创建
如下图所示为对象的创建过程
当虚拟机遇到new指令时
1) 去常量池当中定位类的符号引用;
2) 检查这个类的符号引用是否被加载,解析和初始化过;
3) 如果没有,则进行类加载的过程,第二节会讲到类加载的过程;
4) 如果已经加载过,则虚拟机为对象分配内存;
5) 虚拟机为分配到的内存空间都赋零值;
6) 虚拟机对对象进行必要的设置,比如对象是哪个类的实例,对象的哈希码,对象的GC分代年龄等信息;
7) 执行<init>方法,按照程序意愿初始化对象,即执行类的初始化函数
8) 执行完成之后,就得到了一个新的对象。
2.类加载过程
类的加载过程如下图所示
1) 加载,在加载阶段,虚拟机需要完成以下三件事,首先,通过一个类的全限定名来获取定义此类的二进制字节流;然后将字节流所代表的静态存储结构转化为方法区的运行时数据结构;最后在内存中生成一个代表这个类的java.lang.Class对象,作为在方法区的这个类的各种数据的访问入口;
2) 验证,首先验证Class文件的字节流当中包含的信息是否符合当前虚拟机的要求;然后再验证代码是否会危害虚拟机自身的安全;
3) 准备,在准备阶段会为类变量分配内存,并赋初值;
比如代码;
public static int value = 50;
在准备阶段,会为value分配内存,并赋初值0。在初始化的阶段才会被赋值为50。
4) 解析,在解析阶段,虚拟机将常量池内的符号引用替换为直接引用。
5) 初始化,执行<clinit>方法,它是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。
3.双亲委派模型
Java当中的类都需要由类加载器来加载,其中系统提供了三种类加载器,分别是:
启动类加载器:主要负责加载 <JAVA_HOME>/lib目录当中的类;
扩展类加载器:主要负责加载<JAVA_HOME>/lib/ext目录当中的类;
应用程序加载器:主要负责加载用户类路径上所制定的类库;
另外也可以自己定义类加载器。
双亲委派模型的工作过程是:当一个类加载器收到了类加载请求的时候,它首先不会自己尝试去加载这个类,而是把这个请求委派给它的父亲类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器当中,只有当父加载器反馈自己无法完成这个加载请求时(它的搜索范围当中没有找到所需的类),子加载器才会自己尝试去加载。