1. 类加载的过程
① 加载指的是根据一个类的全限定名将 (class文件) 定义此类的二进制字节流读入内存
虚拟机规范并没有指明二进制文件是从哪里获取,也就是说并不一定是从class
文件中获取,还可以通过以下方式获取
-
运行时计算生成
我们经常使用的动态代理技术就是这样,在java.lang.reflect.Proxy
中使用ProxyGenerator.generateProxyClass
来为特定接口生成形式为*$Proxy
的代理类的二进制字节流 -
由其他文件生成
我们用到的JSP文件也可以生成对应的Class
类 -
从
ZIP
包中读取
常见的就是JAR
,WAR
格式的包的使用
② 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
字节码被加载到方法区
- jdk1.8是放在了元空间,构成了
instanceKlass
的数据结构,这个instanceKlass
是用来描述类的数据结构 - jdk1.7是放在了堆的永久代
③ 在内存中生成一个代表此类的java.lang.Class
对象,作为访问方法区这些运行时数据结构的入口
加载完成之后,虚拟机外部的二进制字节流就按照虚拟机所需要的格式存储在方法区之中,然后在内存中实例化一个java.lang.Class
类型的对象(并没有明确要在堆中)
hotspot
选择将Class
对象存储在方法区中(这点比较特殊,他虽然是对象,但是存储在方法区中)持有instanceKlass
的内存地址(instanceKlass
也持有_java_mirror
对象的内存地址),Java虚拟机规范并没有明确要求一定要存储在方法区或堆区中
这里就涉及到一个oop-klass模型