目录
同步更新于:.idea | Blogs
Java程序的执行流程
一段Java代码首先会被编译成class文件,再由类加载器加载到内存中并由字节码执行引擎一行一行地解释给底层的CPU去执行。(所以说Java是一种半编译半解释的语言,不过鉴于解释执行的效率实在太低了,改进之后就有了我们后面熟悉的热点代码这一说)
类加载机制
什么叫做类加载机制?——虚拟机把描述类的数据从class文件加载到内存中,中间再经历验证、转换解析和初始化,最终得到虚拟机可以直接使用的Java类型的过程就叫做Java类加载机制。
Java类加载过程
- 加载 -> 验证 -> 准备 -> 解析 -> 初始化
验证准备解析合称为连接,该过程描述的仅仅是各阶段的开始顺序,不意味着完成顺序。其中解析阶段和初始化阶段的开始顺序并不严格按照解析在前初始化在后的顺序。
当遇到new关键字时,或者使用到类型所有的属性(static变量)或static方法时会立即执行初始化(当然前面的验证准备解析等自然也就开始了),还有当实例化子类时发现父类还没有实例化时、反射调用一个还没有装载的类时也会立即触发初始化。
- 各个阶段的职责是什么?
加载:完成三件事:1.通过全限定类名获取类的二进制字节流 2.将class文件中的静态存储结构转换成方法区中的动态存储结构 3.在堆中实例化一个对应的class对象,做为外部使用该类数据的接口。
验证:校验传入的二进制流是否符合JVM及Java语义规范,是否会做出对虚拟机内部不利的事情。
准备:为类变量分配内存并赋初始零值。
解析:将符号引用转为直接引用。
初始化:执行类构造器clinit()方法,该方法是javac编译后的产物,由static变量的赋值语句和static代码块生成。
类加载器
加载阶段通过全限定类名从class文件中获取到了二进制流信息,但是并没有规定从哪个地方去获取所需要的类,这个过程交由了类加载器来实现。
在Java模块化之前的版本中,从Java程序员的角度出发一般会使用到三种系统提供的类加载器:启动类加载器(引导类加载器)、扩展类加载器、应用程序类加载器(系统类加载器)。
三种类加载器有各自负责加载的区域;扩展类和应用类都是用户可以直接使用的类加载器;如果没有指定自定义加载器,用户编写的大部分Java代码默认都是由应用程序类加载器加载。
双亲委派模型
我们知道,判断两个类是否相等不仅仅取决于他们是否来自用一份class文件,还取决于是否由同一个类加载器加载。双亲委派模型带来的好处就是保证了Java类加载的一种优先级与有序性。例如一个顶层父类Object类,得益于双亲委派模型,不论是哪一个类加载器去加载它