[读书笔记]Java类加载过程

一. 类的生命周期

类从被加载到虚拟机内存中开始,到卸载出内存为止,有以下(如图)的生命周期:

以上“加载->验证->准备->解析->初始化”称为类的加载过程

Java虚拟机规范中没有对什么时候需要开始类加载的第一阶段进行强制约束,而是交给了虚拟机根据具体实现来自由把握。

但是对于初始化阶段,虚拟机有以下5种必须对类立即进行“初始化”的情况:

(1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类还没初始化就需要马上触发其初始化。常见场景:使用new实例化对象、读取或设置一个类的静态字段(除了编译器处理了的final字段)以及调用一个类的静态方法时。

(2)使用反射(java.lang.reflect包)对类进行调用时,也会触发类的初始化。

(3)当初始化一个类时,发现父类还未初始化时,要先触发父类的初始化。

(4)当虚拟机启动时,用户需要指定一个执行包含main方法的主类,虚拟机会初始化这个类。

(5)当使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,触发对应的这个类的初始化。

以上5种场景的行为称为对一个类进行主动引用,除此之外的引用方式将不会触发类的初始化,称为被动引用。

以下是被动引用的一个列子:

  1. class SuperClass
  2. {
  3. static
  4. {
  5. System.out.println("SuperClass init!");
  6. }
  7. public static int value = 123;
  8. }
  9. class SubClass extends SuperClass
  10. {
  11. static
  12. {
  13. System.out.println("SubClass init!");
  14. }
  15. }
  16. public class NotInitialization
  17. {
  18. public static void main(String[] args)
  19. {
  20. System.out.println(SubClass.value);
  21. }
  22. }

输出结果:

SuperClass init!

123

二.类的加载过程

1.加载

加载阶段进行过程:

(1)通过一个类的全限定名获取定义此类的二进制字节流;

(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;

(3)在内存中生成一个代表这个类的Java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

2.验证

验证是为了确保字节流包含信息符合当前虚拟机的要求,并且是安全的。

大概有四个验证阶段

(1)文件格式验证:验证字节流是否符合Class文件格式的规范;

(2)元数据验证:对字节码描述的信息进行语义分析,目的是对类的元数据信息(数据类型)进行语义校验;

(3)字节码验证:对类方法体进行校验分析;

(4)符号引用验证:对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验。

这里可以做一个优化:因为验证阶段耗时还是挺大的,假如已被重复使用多次并且是验证过的代码即可跳过这个步骤,加快类加载速度。

3.准备

正式为类变量(static)分配内存和设置类变量的初始值,这里的类变量除了被final修饰的。

4.解析

将符号引用替换成直接引用的过程。

5.初始化

执行()类构造方法的过程,即static块语句的执行和变量的复制操作。

来自为知笔记(Wiz)

时间: 2024-10-11 00:19:02

[读书笔记]Java类加载过程的相关文章

[读书笔记]Java类加载器

一.类与类加载器 类加载器除了在类加载阶段的作用外,还确定了对于一个类,都需要由加载它的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性.通俗一点来讲,要判断两个类是否"相等",前提是这两个类必须被同一个类加载器加载,否则这个两个类不"相等". 这里指的"相等",包括类的Class对象的equals()方法.isAssignableFrom()方法.isInstance()方法.instanceof关键字等判断出来的结果. 示例:不同的类

读书笔记-----Java并发编程实战(一)线程安全性

线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet 1 @ThreadSafe 2 public class StatelessFactorizer implements Servlet{ 3 public void service(ServletRequest req,ServletResponse resp){ 4 BigInteger i = extractFromRequest(req); 5 BigInteger[] fact

[读书笔记] java类初始化

以下内容来自周志明的<深入理解java虚拟机>: 类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制. 到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说是字节码). 在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程.

java类加载过程

类加载过程 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Resolution).初始化(Initialization).使用(Using)和卸载(Unloading)7个阶段.其中准备.验证.解析3个部分统称为连接(Linking).如图所示. 加载.验证.准备.初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况

java类加载过程,了解一下?

先了解一下: 什么是类的加载:jvm将class文读取到内存中,经过对class文件的校验.转换解析.初始化最终在jvm的heap和方法区分配内存形成可以被jvm直接使用的类型的过程. 生命周期:7个阶段依次为:Loading(加载)Verification (验证)Preparation (准备)Resolution(连接) Initialization (初始化)Using(使用) Unloading(卸载) 加载Loading 这个阶段jvm完成以下动作:首先  类加载器通过类的全路径限定

java类加载过程以及双亲委派机制

前言:最近两个月公司实行了996上班制,加上了熬了两个通宵上线,状态很不好,头疼.牙疼,一直没有时间和精力写博客,也害怕在这样的状态下写出来的东西出错.为了不让自己荒废学习的劲头和习惯,今天周日,也打算写一篇博客,就算是为了给自己以前立的flag(每个月必须写几篇博客)的实现.那么本次博客的主题我选择了java的类加载过程的探究以及双亲委派机制模型以及它被破坏的场景,搞清楚这个对于我们理解java的类加载过程以及面试中都是很有必要的. 本篇博客的目录 一:类加载器 二:类加载的过程和阶段 三:双

[读书笔记]Java类载入过程

一. 类的生命周期 类从被载入到虚拟机内存中開始,到卸载出内存为止,有下面(如图)的生命周期: 以上"载入->验证->准备->解析->初始化"称为类的载入过程. Java虚拟机规范中没有对什么时候须要開始类载入的第一阶段进行强制约束,而是交给了虚拟机依据详细实现来自由把握. 可是对于初始化阶段,虚拟机有下面5种必须对类立即进行"初始化"的情况: (1)遇到new.getstatic.putstatic或invokestatic这4条字节码指令

[读书笔记]java中的类加载器

以下内容大多来自周志明的<深入理解Java虚拟机>. 类加载器是java的一项创新,也是java流行的重要原因之一,它最初是为了满足java applet的需求而开发出来. 什么是applet? 作为新手,都不知道applet是什么鬼,看看百度百科的解释,应该就明白了: JavaApplet就是用Java语言编写的小应用程序,可以直接嵌入到网页中,并能够产生特殊的效果. 所以Applet就目前来看 我们用不到了,但是类加载器却在类层次划分.OSGI.热部署.代码加密等领域大放异彩,成为了JAV

读书笔记--Java核心技术--基础篇

第三章   Java基本程序设计----------------------------------------------------------------- 在JAVA中,/* */注释不能嵌套 Java有8种基本类型 4种整型:int, long, short, byte:长整型后缀加L,0x前缀表示十六进制,0前缀表示八进制,0b前缀表示二进制 2种浮点类型:float, double:后缀F表示float,后缀D表示double,默认使用double 常量Double.POSITIV