JVM知识点(二) classLoader源码分析

JVM知识点划分

  • class文件结构
  • classLoader
  • jvm运行时数据区
  • 垃圾回收器及垃圾回收算法
  • jit

定义

ClassLoader 顾名思义就是类加载器,ClassLoader 作用

  • 负责将 Class 加载到 JVM 中
  • 审查每个类由谁加载(父优先的等级加载机制)
  • 将 Class 字节码重新解析成 JVM 统一要求的对象格式

类加载器分类

系统级别

  • 启动类加载器(C实现)
  • 扩展类加载器(java实现)
  • 系统类加载器(APP类加载器)

用户级别

自定义类加载器,集成自ClassLoader

层级结构

在这里插入图片描述

代码实现

启动类加载器

public static void BootStrapClassLoader() {
    
    

        //获取启动类的加载器的加载目录
        String bootStrapClassLoaderPath = System.getProperty("sun.boot.class.path");
        //把加载后的目录转化为集合
        List<String> bootStrapClassLoaderPathList = Arrays.asList(bootStrapClassLoaderPath.split(";"));

        for (String path : bootStrapClassLoaderPathList) {
    
    
            System.out.println("[启动类加载器-加载目录]" + path);
        }
    }

输出:

[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\resources.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\rt.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\sunrsasign.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jsse.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jce.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\charsets.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jfr.jar
[启动类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\classes

扩展类加载器

 public static void ExtClassLoader() {
    
    

        //获取扩展类的加载器的加载目录
        String extClassLoaderPath = System.getProperty("java.ext.dirs");
        //把加载后的目录转化为集合
        List<String> extClassLoaderPathList = Arrays.asList(extClassLoaderPath.split(";"));

        for (String path : extClassLoaderPathList) {
    
    
            System.out.println("[扩展类加载器-加载目录]" + path);
        }
    }

输出:

[扩展类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext
[扩展类加载器-加载目录]C:\WINDOWS\Sun\Java\lib\ext

应用类加载器

public static void APPClassLoader() {
    
    

        //应用类的加载器的加载目录
        String appClassLoaderPath = System.getProperty("java.class.path");
        //把加载后的目录转化为集合
        List<String> appClassLoaderPathList = Arrays.asList(appClassLoaderPath.split(";"));

        for (String path : appClassLoaderPathList) {
    
    
            System.out.println("[应用类加载器-加载目录]" + path);
        }
    }

输出


[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\charsets.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\deploy.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\access-bridge-64.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\cldrdata.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\dnsns.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\jaccess.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\jfxrt.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\localedata.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\nashorn.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\ojdbc6-11.2.0.3.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunec.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunjce_provider.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunmscapi.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunpkcs11.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\zipfs.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\javaws.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jce.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jfr.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jfxswt.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\jsse.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\management-agent.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\plugin.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\resources.jar
[应用类加载器-加载目录]C:\Program Files\Java\jdk1.8.0_91\jre\lib\rt.jar
[应用类加载器-加载目录]C:\work\demo\jxs-parent\jxs-user\target\classes
[应用类加载器-加载目录]C:\work\demo\jxs-parent\jxs-common\jxs-common-base\target\classes
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-web\2.2.5.RELEASE\spring-boot-starter-web-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter\2.2.5.RELEASE\spring-boot-starter-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot\2.2.5.RELEASE\spring-boot-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-logging\2.2.5.RELEASE\spring-boot-starter-logging-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-core\5.2.4.RELEASE\spring-core-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-jcl\5.2.4.RELEASE\spring-jcl-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-json\2.2.5.RELEASE\spring-boot-starter-json-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\core\jackson-databind\2.10.2\jackson-databind-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\core\jackson-core\2.10.2\jackson-core-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.10.2\jackson-datatype-jdk8-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.10.2\jackson-datatype-jsr310-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\module\jackson-module-parameter-names\2.10.2\jackson-module-parameter-names-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-tomcat\2.2.5.RELEASE\spring-boot-starter-tomcat-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\apache\tomcat\embed\tomcat-embed-core\9.0.31\tomcat-embed-core-9.0.31.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\apache\tomcat\embed\tomcat-embed-el\9.0.31\tomcat-embed-el-9.0.31.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.31\tomcat-embed-websocket-9.0.31.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-validation\2.2.5.RELEASE\spring-boot-starter-validation-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\hibernate\validator\hibernate-validator\6.0.18.Final\hibernate-validator-6.0.18.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-web\5.2.4.RELEASE\spring-web-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-beans\5.2.4.RELEASE\spring-beans-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-webmvc\5.2.4.RELEASE\spring-webmvc-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-aop\5.2.4.RELEASE\spring-aop-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-context\5.2.4.RELEASE\spring-context-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-expression\5.2.4.RELEASE\spring-expression-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-actuator\2.2.5.RELEASE\spring-boot-starter-actuator-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-actuator-autoconfigure\2.2.5.RELEASE\spring-boot-actuator-autoconfigure-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-actuator\2.2.5.RELEASE\spring-boot-actuator-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\micrometer\micrometer-core\1.3.5\micrometer-core-1.3.5.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\hdrhistogram\HdrHistogram\2.1.11\HdrHistogram-2.1.11.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\latencyutils\LatencyUtils\2.0.3\LatencyUtils-2.0.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-data-jpa\2.2.5.RELEASE\spring-boot-starter-data-jpa-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-aop\2.2.5.RELEASE\spring-boot-starter-aop-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-starter-jdbc\2.2.5.RELEASE\spring-boot-starter-jdbc-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\zaxxer\HikariCP\3.4.2\HikariCP-3.4.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-jdbc\5.2.4.RELEASE\spring-jdbc-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\hibernate\hibernate-core\5.4.12.Final\hibernate-core-5.4.12.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\jboss\logging\jboss-logging\3.4.1.Final\jboss-logging-3.4.1.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\javassist\javassist\3.24.0-GA\javassist-3.24.0-GA.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\net\bytebuddy\byte-buddy\1.10.8\byte-buddy-1.10.8.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\antlr\antlr\2.7.7\antlr-2.7.7.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\jboss\jandex\2.1.1.Final\jandex-2.1.1.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\dom4j\dom4j\2.1.1\dom4j-2.1.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\hibernate\common\hibernate-commons-annotations\5.1.0.Final\hibernate-commons-annotations-5.1.0.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\glassfish\jaxb\jaxb-runtime\2.3.2\jaxb-runtime-2.3.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\jakarta\xml\bind\jakarta.xml.bind-api\2.3.2\jakarta.xml.bind-api-2.3.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\glassfish\jaxb\txw2\2.3.2\txw2-2.3.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\sun\istack\istack-commons-runtime\3.0.8\istack-commons-runtime-3.0.8.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\jvnet\staxex\stax-ex\1.8.1\stax-ex-1.8.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\sun\xml\fastinfoset\FastInfoset\1.2.16\FastInfoset-1.2.16.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\data\spring-data-jpa\2.2.5.RELEASE\spring-data-jpa-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\data\spring-data-commons\2.2.5.RELEASE\spring-data-commons-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-orm\5.2.4.RELEASE\spring-orm-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-tx\5.2.4.RELEASE\spring-tx-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\spring-aspects\5.2.4.RELEASE\spring-aspects-5.2.4.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\mysql\mysql-connector-java\8.0.19\mysql-connector-java-8.0.19.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\alibaba\druid-spring-boot-starter\1.1.20\druid-spring-boot-starter-1.1.20.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\alibaba\druid\1.1.20\druid-1.1.20.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\boot\spring-boot-autoconfigure\2.2.5.RELEASE\spring-boot-autoconfigure-2.2.5.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-swagger2\2.9.2\springfox-swagger2-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\swagger\swagger-annotations\1.5.20\swagger-annotations-1.5.20.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\swagger\swagger-models\1.5.20\swagger-models-1.5.20.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\jackson\core\jackson-annotations\2.10.2\jackson-annotations-2.10.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-spi\2.9.2\springfox-spi-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-core\2.9.2\springfox-core-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-schema\2.9.2\springfox-schema-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-swagger-common\2.9.2\springfox-swagger-common-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-spring-web\2.9.2\springfox-spring-web-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\guava\guava\28.2-android\guava-28.2-android.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\checkerframework\checker-compat-qual\2.5.5\checker-compat-qual-2.5.5.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\errorprone\error_prone_annotations\2.3.4\error_prone_annotations-2.3.4.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\plugin\spring-plugin-core\1.2.0.RELEASE\spring-plugin-core-1.2.0.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\springframework\plugin\spring-plugin-metadata\1.2.0.RELEASE\spring-plugin-metadata-1.2.0.RELEASE.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\mapstruct\mapstruct\1.2.0.Final\mapstruct-1.2.0.Final.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\io\springfox\springfox-swagger-ui\2.9.2\springfox-swagger-ui-2.9.2.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus-boot-starter\3.1.0\mybatis-plus-boot-starter-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus\3.1.0\mybatis-plus-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus-generator\3.1.0\mybatis-plus-generator-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus-extension\3.1.0\mybatis-plus-extension-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus-core\3.1.0\mybatis-plus-core-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\baomidou\mybatis-plus-annotation\3.1.0\mybatis-plus-annotation-3.1.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\mybatis\mybatis\3.5.0\mybatis-3.5.0.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\com\github\jsqlparser\jsqlparser\1.4\jsqlparser-1.4.jar
[应用类加载器-加载目录]C:\work\maven\Repositories\org\mybatis\mybatis-spring\2.0.0\mybatis-spring-2.0.0.jar
[应用类加载器-加载目录]C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar

双亲委派原则

代码实现

 System.out.println("当前加载器:"+DiffClassLoader.class.getClassLoader());
 System.out.println("当前加载器-父类:"+DiffClassLoader.class.getClassLoader().getParent());
 System.out.println("当前加载器-父类-父类:"+DiffClassLoader.class.getClassLoader().getParent().getParent());

输出:

当前加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
当前加载器-父类:sun.misc.Launcher$ExtClassLoader@37f8bb67
当前加载器-父类-父类:null

源码探索

什么时候出发类加载

  • 访问类的静态变量 (除常量【 被final修辞的静态变量】 原因:常量一种特殊的变量,因为编译器把他们当作值(value)而不是域(field)来对待。如果你的代码中用到了常变量(constant variable),编译器并不会生成字节码来从对象中载入域的值,而是直接把这个值插入到字节码中。这是一种很有用的优化,但是如果你需要改变final域的值那么每一块用到那个域的代码都需要重新编译。
  • 访问类的静态方法
  • 虚拟机启动时,定义了main()方法的那个类先初始化
  • 创建类的实例 new指令
  • 反射 如( Class.forName(“my.xyz.Test”) )
  • 子类初始化,一定会出发父类加载

初始化一定会类加载
类加载不一定会触发初始化

重要方法

loadClass()


/**
   * 加载指定的限定名,默认实现以下方法:
   * 1. 调用 findLoadedClass(String)方法来校验class是否被加载
   * 2. 调用loadClass(String) 方法,在父类加载器上,如果父类加载器是null,则调用虚拟机		提供的加载器,即为BootStrapClassLoader
   * 3. 调用findClass(String) 方法, 来寻找class
   *  
   * 参数:
   * name:全限定名
   * resolve 如果是true 解决这个类
   * 
    *
    * 
    * 如果在上述步骤中找到类, 且  "resolve" 属性是true  ,将会调用resolveClass(Class)
    * 在最后返回class时
    * 
    * 子类加载器鼓励去实现 findClass(String)方法
    * 
    */
   protected Class<?> loadClass(String name, boolean resolve)
       throws ClassNotFoundException
   {
    
    
       synchronized (getClassLoadingLock(name)) {
    
    
           // 1. 校验类是否被加载
           Class<?> c = findLoadedClass(name);
           if (c == null) {
    
    
               long t0 = System.nanoTime();
               try {
    
    
                   if (parent != null) {
    
    
                   //父加载器不为空则调用父加载器的loadClass
                       c = parent.loadClass(name, false);
                   } else {
    
    
                   //如果为空调用启动类加载器
                       c = findBootstrapClassOrNull(name);
                   }
               } catch (ClassNotFoundException e) {
    
    
                   // ClassNotFoundException thrown if class not found
                   // from the non-null parent class loader
               }

               if (c == null) {
    
    
                   //如果分类加载器没有找到,则调用findClass 来寻找类
                   long t1 = System.nanoTime();
                   c = findClass(name);

                   // this is the defining class loader; record the stats
                   sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                   sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                   sun.misc.PerfCounter.getFindClasses().increment();
               }
           }
           if (resolve) {
    
    
           调用resolveClass()
               resolveClass(c);
           }
           return c;
       }
   }

加载流程

在这里插入图片描述

扫描二维码关注公众号,回复: 12352410 查看本文章

手写自定义加载器

新建需要加载的类

package com.jxs.user.classLoader;

public class Person {
    
    

    public void say() {
    
    
        System.out.println("Say Hello");
    }
}

自定义CustomerClassLoader


package com.jxs.user.classLoader;

import java.io.*;

public class CustomerClassLoader extends ClassLoader {
    
    

    private String mLibPath;


    public CustomerClassLoader(String path) {
    
    
        // TODO Auto-generated constructor stub
        mLibPath = path;
    }


    /**
     * Finds the class with the specified <a href="#name">binary name</a>.
     * This method should be overridden by class loader implementations that
     * follow the delegation model for loading classes, and will be invoked by
     * the {@link #loadClass <tt>loadClass</tt>} method after checking the
     * parent class loader for the requested class.  The default implementation
     * throws a <tt>ClassNotFoundException</tt>.
     *
     * @param name The <a href="#name">binary name</a> of the class
     * @return The resulting <tt>Class</tt> object
     * @throws ClassNotFoundException If the class could not be found
     * @since 1.2
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
    
    

        String fileName = getFileName(name);
        //加载文件
        File file = new File(mLibPath, fileName);

        try {
    
    
            FileInputStream is = new FileInputStream(file);

            //输出流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            int len = 0;
            if ((len = is.read()) != -1) {
    
    
                bos.write(len);
            }
            byte[] data = bos.toByteArray();

            is.close();
            bos.close();

            return defineClass(name, data, 0, data.length);
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return super.findClass(name);
    }

    /**
     * @param name 获取要加载 的class文件名
     * @return
     */
    private String getFileName(String name) {
    
    
        // TODO Auto-generated method stub
        int index = name.lastIndexOf('.');
        if (index == -1) {
    
    
            return name + ".class";
        } else {
    
    
            return name.substring(index + 1) + ".class";
        }
    }
}

测试类

package com.jxs.user.classLoader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ClassLoaderTest {
    
    

    public static void main(String[] args) {
    
    
        // TODO Auto-generated method stub

        //创建自定义classloader对象。
        CustomerClassLoader diskLoader = new CustomerClassLoader("C:\\work\\demo\\jxs-parent\\jxs-user\\target\\classes");
        try {
    
    
            //加载class文件
            Class c = diskLoader.loadClass("com.jxs.user.classLoader.Person");

            if(c != null){
    
    
                try {
    
    
                    Object obj = c.newInstance();
                    Method method = c.getDeclaredMethod("say",null);
                    //通过反射调用Test类的say方法
                    method.invoke(obj, null);
                } catch (InstantiationException | IllegalAccessException
                        | NoSuchMethodException
                        | SecurityException |
                        IllegalArgumentException |
                        InvocationTargetException e) {
    
    
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } catch (ClassNotFoundException e) {
    
    
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

输出:

Say Hello

猜你喜欢

转载自blog.csdn.net/jinian2016/article/details/108561485