我们都知道以 .java
结尾的 java 源文件,经过编译之后会变成 .class
结尾的字节码文件。jvm 通过类加载器来加载字节码文件,然后再执行程序。
那么,什么时候类加载器会加载一个类呢?用到这个类的时候,jvm的类加载器就会加载这个类。用到这两个字说起来很抽象,我用代码和图例来说明。
有下面这样一段代码,一个类emergencyplan
,里面有一个main()
函数,main()
函数做的事情是创建了一个 account 对象。
public class emergencyplan { public static void main(string[] args) { account account = new account(); } }
我们应该知道运行 jvm 就相当于启动了一个 java 的进程,它会从程序的主函数,即main()
函数开始执行。所以类加载的步骤是这样的:
emergencyplan
emergencyplan
使用了account
,所以继续加载account
类加载机制总共有这样7个步骤:加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载。接下来先把每个阶段在做什么讲一下,再着重对比一下准备阶段和初始化阶段。
用代码和画图来说明一下准备阶段和初始化阶段。
public class emergencyplan { public static int id = configuration.getint("plan_id"); }
这段代码说的是emergencyplan
这个类有一个变量id
,通过getint()
为其赋值:
id
开辟一个内存空间,但不会执行赋值操作,仅仅是赋予一个初值0。getint()
为变量id
初始化值。类加载的过程就变成了下图所示的样子:
jvm进行类加载是通过类加载器完成,类加载器是一种亲子层级结构的模型。java里面的类加载器有这样几种:
$java_home/lib
目录。那什么是双亲委派模型呢?类加载器是一种亲自层级结构,就像下图所示:
比如要加载上面的emergencyplan
类,应用程序类加载器会先问它的父亲扩展类加载器,你能帮我加载么?扩展类加载器会再问它的父亲启动类加载器,你能帮我加载么?
显然emergencyplan
是一个应用程序类。启动类加载器会告诉扩展类加载器,你自己去加载;扩展类加载器就会告诉应该程序类加载器,你自己去加载。最后,应用程序类加载器就自己加载了emergencyplan
。
最后来在类加载的流程图上,把双亲委派模型也添加上去。
如对本文有疑问, 点击进行留言回复!!
荐 JAVA实现对已有数据库的插入、删除、更改、查询操作详细解释
荐 shell脚本自动化创建虚拟机的基本配置--tomcat--mysql--jdk--maven
网友评论