From a1b2931ec74f8be413f41da2b821c2c36d55b570 Mon Sep 17 00:00:00 2001 From: "shuang.kou" Date: Fri, 13 Mar 2020 17:17:49 +0800 Subject: [PATCH] =?UTF-8?q?Update=20=E7=B1=BB=E5=8A=A0=E8=BD=BD=E8=BF=87?= =?UTF-8?q?=E7=A8=8B.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/java/jvm/类加载过程.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/java/jvm/类加载过程.md b/docs/java/jvm/类加载过程.md index 70499775..58294409 100644 --- a/docs/java/jvm/类加载过程.md +++ b/docs/java/jvm/类加载过程.md @@ -76,13 +76,18 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 对于`()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 `()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。 -对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化: +对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化(只有主动去使用类才会初始化类): 1. 当遇到 new 、 getstatic、putstatic或invokestatic 这4条直接码指令时,比如 new 一个类,读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。 -2. 使用 `java.lang.reflect` 包的方法对类进行反射调用时 ,如果类没初始化,需要触发其初始化。 + - 当jvm执行new指令时会初始化类。即当程序创建一个类的实例对象。 + - 当jvm执行getstatic指令时会初始化类。即程序访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)。 + - 当jvm执行putstatic指令时会初始化类。即程序给类的静态变量赋值。 + - 当jvm执行invokestatic指令时会初始化类。即程序调用类的静态方法。 +2. 使用 `java.lang.reflect` 包的方法对类进行反射调用时如Class.forname("..."),newInstance()等等。 ,如果类没初始化,需要触发其初始化。 3. 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。 4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。 -5. 当使用 JDK1.7 的动态动态语言时,如果一个 MethodHandle 实例的最后解析结构为 REF_getStatic、REF_putStatic、REF_invokeStatic 的方法句柄,并且这个句柄没有初始化,则需要先触发器初始化。 +5. MethodHandle和VarHandle可以看作是轻量级的反射调用机制,而要想使用这2个调用, + 就必须先使用findStaticVarHandle来初始化要调用的类。 ## 卸载