首页 > 其他 > 详细

JVM - 类加载过程

时间:2020-08-26 14:24:43      阅读:58      评论:0      收藏:0      [点我收藏+]

类加载主要有三个过程:loading 、linking 、initializing

其中linking又分为三个步骤:verification 、preparation 、resolution

技术分享图片

1:loading是把一个class文件加载到内存中

2:接下来就是Linking,分为三小步

  2.1:verification 用来校验加载进来的class文件是否符合class文件标准,如果不符合直接拒绝

  2.2:preparation 将class文件的静态变量赋默认值而不是初始值,如 static int i = 8;这个步骤并不是将 i 赋值为8,而是赋值默认值0

  2.3:resolution 把class文件常量池中用到的符号引用转换成内存地址,可以访问到的内容

3:initialzing 成为初始化,静态变量这个时候才会被赋值为初始值

 

下面为loading的过程图

技术分享图片

 

类加载器的加载过程是分成不同的层次来加载的,不同的类加载器加载不同的class文件,Bootstrap > Extension > App > Custom(自定义类加载器)

1:第一个类加载器:Bootstrap 称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库

2:第二个类加载器:Extension 是用来加载扩展类的,主要加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包

3:第三个类加载器:Application 称为系统类加载器,负责在JVM启动时,加载来自Java中的classpath或者java.class.path系统属性或者

           CLASSPATH操作系统属性所指定的jar类包和类路径

4:第四个类加载器:CustomClassLoader(自定义加载器)

 

文字描述:

用比较通俗的话来解释loading这个过程,当有一个类需要被加载时,首先要判断这个类是否已经被加载到内存,判断加载与否的过程是有顺序的,

如果有自己定义的类加载器,会先到custom class loader 的cache(缓存)中去找是否已经加载,若已加载直接返回结果,

否则到App的cache中查找,如果已经存在直接返回,如果不存在,到Extension中查找,存在直接返回,

不存在继续向父加载器中寻找直到Bootstrap顶层,如果依然没找到,那就是没有加载器加载过这个类,需要委派对应的加载器来加载,

先看看这个类是否在自己的加载范围内,如果是直接加载返回结果,若不是继续向下委派,以此类推直到最下级,

如果最终也没能加载,就会直接抛异常 ClassNotFoundException,这就是双亲委派模式。

 

  public static void main(String[] args) {
System.out.println(
"----------------Bootstrap加载类----------------"); String property = System.getProperty("sun.boot.class.path"); String s = property.replaceAll(";", System.lineSeparator()); System.out.println(s); System.out.println("-------------------Ext加载类-------------------"); String property1 = System.getProperty("java.ext.dirs"); String s1 = property1.replaceAll(";", System.lineSeparator()); System.out.println(s1); System.out.println("-------------------App加载类-------------------"); String property2 = System.getProperty("java.class.path"); String s2 = property2.replaceAll(";", System.lineSeparator()); System.out.println(s2); }

----------------Bootstrap加载类----------------
C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\sunrsasign.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar
C:\Program Files\Java\jdk1.8.0_201\jre\classes


-------------------Ext加载类-------------------
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext
C:\Windows\Sun\Java\lib\ext


-------------------App加载类-------------------
C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar
C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar
E:\Project\Java\out\production\Java
D:\IntelliJ IDEA\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar

 

为什么要搞双亲委派?

主要是为了安全,这里可以使用反证法,如果任何加载器都可以把Class加载到内存中,我们就可以自定义加载器来加载java.lang.string,在打包时可以把密码存为String对象,这样会造成安全问题

 

如何打破双亲委派?

重写loadclass方法

 

自定义加载器

我们自定义的类加载器只需要继承ClassLoader,并覆盖findClass方法

JVM - 类加载过程

原文:https://www.cnblogs.com/yan-sh/p/13418742.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!