指令:java -server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly com.bayern.shengsiyuan.jvm_lecture.lesson2.MyTest5 > ~/Desktop/MyTest5.asm


发生的时机
Java虚拟机规范中并没有进行强制约束一个类需要在什么时候开始“加载”,但是Java严格规定了类被“初始化”阶段的情况,一个类一旦需要被“初始化”,它一定会先被“加载”。(“加载”、“验证”、“准备”需要在“初始化”之前开始)
而一个不会被“初始化”的类也不能说明它没有被“加载”,这是不能确定的。
流程
在加载阶段,虚拟机需要完成以下3件事情:
① 通过一个类的全限定名来获取定义此类的二进制字节流。
注意,这里并没有指明“二进制字节流”要从一个’.class’文件中获取,准确地说是根本没有指明要从哪里获取、怎样获取。
通常可以通过如下方式获取类的二进制字节流:
[1] 从本地系统中直接加载
[2] 从网络中获取,这种场景最典型的应用就是Applet。
[3] 从zip,jar等归档文件中加载’.class’文件
[4] 从专有中读取。
[5] 运行时计算生成,这种场景使用得最多的就是动态代理技术,在java.lang.reflect.Proxy中,就是用了ProxyGenerator.generateProxyClass来为特定接口生成形式为“*$Proxy”的代理类的二进制字节流。
[6] 。。。。。。
② 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。(在JDK 8中Class对象会被放在“元空间”)

③ 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式由虚拟机实现自行定义,虚拟机规范未规定此区域的具体数据结构。然后在内存中实例化一个java.lang.Class类的对象(并没有明确规定是在Java堆中,对于HotSpot虚拟机而言,Class对象比较特殊,它虽然是对象,但是存放在方法区里面),这个对象将作为程序访问方法区中的这些类型数据的外部接口。
首先,方法区中存储了该类的信息,以特定的数据结构表示。而java.lang.Class类对象只是用于给外界访问该数据结构的一个入口。
加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
关于“非数组类”的加载:
相对于类加载过程的其他阶段,一个非数组类的加载阶段(准确地说,是加载阶段中获取类的二进制字节流的动作)是开发人员可控性最强的,因为加载阶段既可以使用系统提供的引导类加载器来完成,也可以由用户自定义的类加载器去完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式(即重写一个类加载器的loadClass()方法)。
关于“数组类”的加载:
对于数组类而言,情况就有所不同,数组类本身不通过类加载器创建,它是由Java虚拟机在运行时直接创建的。但数组类与类加载器仍然有很密切的关系,因为数组类的元素类型(Element Type,指的是数组去掉所有维度的类型)最终是要靠类加载器去创建。
Q:我们常说数组是由组件构成的。什么是组件了?
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-80669-5.html
嚇哭本寶寶了
不听轻则制裁