JVM实验二:类加载机制

一、类加载介绍

(1)加载

根据类的全限定名获取类的二进制流;

将类的静态数据结构转换成运行时数据结构;

生成class文件作为方法区的访问入口(个人理解:加载就是将静态的编译完成的class文件加载到方法区)

(2)验证

包括:文件格式验证/元数据验证/字节码验证/符号引用验证

(3)准备

为类变量赋初值

(4)解析

将符号引用转换为直接引用

(5)初始化

给类变量分配内存并赋初始值,执行静态代码块

 

二、实验---验证对象数组的加载状态

 1 public class Singleton {
 2     private Singleton() {
 3     }
 4 
 5     private static class LazyHolder {
 6         static final Singleton INSTANCE = new Singleton();
 7 
 8         static {
 9             System.out.println("LazyHolder.");
10         }
11     }
12 
13     public static Object getInstance(boolean flag) {
14         if (flag) return new LazyHolder[2];
15         return LazyHolder.INSTANCE;
16     }
17 
18     public static void main(String[] args) {
19         getInstance(true);
20         System.out.println("----");
21         getInstance(false);
22     }
23 }

上述的Java代码中,第14行新建LazyHolder对象数组,15行新建LazyHolder对象,接下来验证在执行第14行时LazyHolder类的加载情况

 

(1)验证是否加载

验证类是否加载只需要添加虚拟机参数    -XX:+TraceClassLoading //会打印加载日志

结论:加载了元素类

 

(2)验证是否“验证”

java -cp ./asmtools.jar org.openjdk.asmtools.jdis.Main Singleton\$LazyHolder.class > Singleton\$LazyHolder.jasm.1 

#将构造方法的栈大小设置为0,本来是1,用于存放this对象,如果存在“验证”阶段,代码将无法通过而爆出异常
awk 'NR==1,/stack 1/{sub(/stack 1/, "stack 0")} 1' Singleton\$LazyHolder.jasm.1 > Singleton\$LazyHolder.jasm

java -cp ./asmtools.jar org.openjdk.asmtools.jasm.Main Singleton\$LazyHolder.jasm

java -verbose:class Singleton

将字节码故意修改为错误的字节码,构造函数的栈大小设置为0,因为构造函数栈的0号参数默认是this实例对象,因此这样的字节码是无法通过验证的

 

 

 执行结果显示异常,因此显然此类已经被验证过了

结论:验证了元素类

 

 (3)验证初始化

执行Java代码,结果为:

----
LazyHolder.

显然并没有执行元素类的静态代码块

结论:没有初始化

 

(4)实验结论

在执行元素类的创建时,例如Object obj = new Object()

显然会执行类的加载、链接、初始化

 

在执行元素类数组的创建时,例如Object[] objs = new Object[1]

会执行类的加载、链接,但不会执行初始化

 

posted @ 2020-12-09 00:20  kozz  阅读(176)  评论(0)    收藏  举报