Java类加载阶段的一些细节
注意,本文所说的加载,是类加载这个过程的第一个阶段,而不是指的类加载的全部过程
加载(Loading)
从不同的来源将类文件(.class)转化为二进制流加载到内存中,来源可以是本地磁盘、jar包中的类、甚至可以从网络上动态下载类。然后会通过这个二进制流将数据转化成一个代表类的Class对象,并且在元空间中存储该类的信息
这里有一个容易混淆的概念,方法区,永久代以及元空间的关系。方法区只是一个规范,而永久代和元空间是对这套规范的实现,永久代是JDK8之前的实现方式,而元空间是JDK8及之后的实现方式。永久代和元空间的区别在于,永久代在JVM的堆内存中,而元空间在本地内存中,即操作系统中可用内存大小,其大小不受
-Xms
和-Xmx
的限制,减少了OOM发生的频率。
静态常量池
编译期确定,存储在.class文件中,可以通过javap -v -c XXX.class
查看
动态常量池
又称运行时常量池,是JVM在加载类时,将静态常量池加载到元空间后的产物,这意味着它是位于元空间的。动态常量池中的数据与静态常量池中的数据基本相同,但是有着更加灵活的特性,包括可实时动态向其中添加新的对象。
动态常量池还与动态解析相关,其中存放的符号引用会在解析成功后替换为直接引用,若解析失败,则会被JVM标记,防止下一次再次尝试解析