【JVM类的加载】第四天 自定义类的复杂加载以及命名空间详细学习以及总结类加载器的好处

自定义情况下类的复杂加载

实例1
编写对应两个类MyCat 和 MySample

public class MyCat {
    public MyCat() {
        System.out.println("MyCat is loaded by:" +this.getClass().getClassLoader());
    }
}
public class MySample {
    public MySample() {
        System.out.println("MySample is loaded by:" +this.getClass().getClassLoader());

        new MyCat();
    }
}

测试

/*
    关于命名空间的重要说明

    子加载器所加载的类能够访问父加载器所加载的类
    父加载器所加载的类无法访问到子加载器所加载的类

 */
    public static void main(String[] args) throws Exception {
        Test16 loader1 = new Test16("loader1");

        //将指定类加载到jvm中
        Class<?> aClass = loader1.loadClass("com.example.demo.com.jvm.MySample");

        System.out.println("class: "+aClass.hashCode());

        //如果这行注释掉,那么并不会实例化MySample对象,即MySample构造方法不会被调用
        //因此不会实例化MyCat对象,即没有对MyCat进行主动使用,这里就不会加载MyCat Class(某些例子JVM会预料到某个类的使用预先加载)
        Object o = aClass.newInstance();
    }
**此时因为MyCat  和 MySample .class文件都在classpath下 所以此时都是appLoaderClass类加载器去加载
class: 1694819250
MySample is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2
MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2

基于上例改造

此时将对应的路径改为E:\cx\ 不再类路径下 删除MySample.class和MyCat.class

/*
    关于命名空间的重要说明

    子加载器所加载的类能够访问父加载器所加载的类
    父加载器所加载的类无法访问到子加载器所加载的类

 */
public class MyTest17_1 {

    public static void main(String[] args) throws Exception {
        Test16 loader1 = new Test16("loader1");
        loader1.setPath("E:\\cx\\");
        //将指定类加载到jvm中
        Class<?> aClass = loader1.loadClass("com.example.demo.com.jvm.MySample");

        System.out.println("class: "+aClass.hashCode());

        //如果这行注释掉,那么并不会实例化MySample对象,即MySample构造方法不会被调用
        //因此不会实例化MyCat对象,即没有对MyCat进行主动使用,这里就不会加载MyCat Class(某些例子JVM会预料到某个类的使用预先加载)
        Object o = aClass.newInstance();
    }

    
}


当MyCat 和 MySample.class文件不在classpath下 程序运行指定加载MySample
先调用自定义类加载器 反射创建实例 调用对应构造方法 中new Mycat Mycat 继续类加载

打印如下

findClass invoked:com.example.demo.com.jvm.MySample
class loader name: loader1
class: 1651191114
MySample is loaded by:com.example.demo.com.jvm.Test16@6504e3b2
因为MyCat在MySample类下 创建实例所以也是由加载MySample的类加载器或以上的父类加载器加载(双亲委托加载
findClass invoked:com.example.demo.com.jvm.MyCat
class loader name: loader1
MyCat is loaded by:com.example.demo.com.jvm.Test16@6504e3b2

基于上例

在classpath下将MyCat.class删除 不删除 MySample.class

此时打印的

class: 1694819250
MySample is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2
因为MyCat在MySample类下 创建实例所以也是由加载MySample的类加载器以上的父类加载器加载(双亲委托 往下的不考虑)根和扩展无法加载
此时委托给AppClassLoader加载 但是在calssPath下并没有找到MyCat.class 此时是从appClassLoader自上而下往上找无法找到 所以程序报错
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/demo/com/jvm/MyCat
	at com.example.demo.com.jvm.MySample.<init>(MySample.java:7)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at com.example.demo.com.jvm.MyTest17_1.main(MyTest17_1.java:15)
Caused by: java.lang.ClassNotFoundException: com.example.demo.com.jvm.MyCat
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 7 more

基于上例

在classpath下将MySample.class删除 不删除 MyCat.class

findClass invoked:com.example.demo.com.jvm.MySample
class loader name: loader1
class: 1651191114
当指定了对应的path 自定义类加载器尝试让父类加载该类 自定义的所有父类都不能加载所以自己加载
MySample is loaded by:com.example.demo.com.jvm.Test16@6504e3b2
当在 new myCat实例时 此时自定义类加载器先委托给父类加载器 
根加载器和扩展类加载器无法加载 而系统类加载器可以加载所以直接加载 直接初始化 返回对象
MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2

基于上例改造

修改MyCat.java 删除classpath下的MySample.class

public class MyCat {
    public MyCat() {
        System.out.println("MyCat is loaded by:" +this.getClass().getClassLoader());
	
		//新加 获取MySample的Class
        System.out.println("from MyCat: "+MySample.class);
    }


}

此时程序报错 得到命名空间的一个中的结论

findClass invoked:com.example.demo.com.jvm.MySample
class loader name: loader1
class: 1651191114
MySample is loaded by:com.example.demo.com.jvm.Test16@6504e3b2
MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2

因为MyCat的类加载器是AppClassLoader MySample 的类加载器是自定义Test16 子类加载器加载的类可以看到父类加载器加载的类 
父类加载器加载的类看不到子类加载器加载的类的所有信息
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/demo/com/jvm/MySample
	at com.example.demo.com.jvm.MyCat.<init>(MyCat.java:7)
	at com.example.demo.com.jvm.MySample.<init>(MySample.java:7)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at com.example.demo.com.jvm.MyTest17_1.main(MyTest17_1.java:15)
Caused by: java.lang.ClassNotFoundException: com.example.demo.com.jvm.MySample
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 8 more

命名空间(Test21)

在这里插入图片描述
命名空间由该加载器及所有的父加载器所加载的类组成 所以父类看不到子类加载器加载的类的所有类容

基于上例


public class MyCat {
    public MyCat() {
        System.out.println("MyCat is loaded by:" +this.getClass().getClassLoader());

//        System.out.println("from MyCat: "+MySample.class);
    }

}

public class MySample {
    public MySample() {
        System.out.println("MySample is loaded by:" +this.getClass().getClassLoader());

        new MyCat();

        System.out.println("from MySample: "+MyCat.class);
    }
}

重写编译下 将编译好的.class放到指定文件,删除MySample.class文件

findClass invoked:com.example.demo.com.jvm.MySample
class loader name: loader1
class: 1651191114
MySample 自定义  MyCat appClassLoader
MySample is loaded by:com.example.demo.com.jvm.Test16@6504e3b2
MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2
from MySample: class com.example.demo.com.jvm.MyCat

此时证明 父类加载器加载的类无法看子类加载器加载类的所有内容 但是子类加载器加载的类 可以看到父类加载器加载类的所有内容

JVM原生类加载器加载目录解析

public class MyTest18 {

    public static void main(String[] args) {
        System.out.println(System.getProperty("sun.boot.class.path"));//根类加载器
        System.out.println(System.getProperty("java.ext.dirs"));//扩展类加载器
        System.out.println(System.getProperty("java.class.path"));//应用类加载器  当在编译之后的.class文件会被放到classes下 所以会被该类加载器加载
    }
}

C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\classes
C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\workspaces\zookeeper\target\classes;C:\Users\Admin\.m2\repository\com\google\zxing\core\3.3.0\core-3.3.0.jar;C:\Users\Admin\.m2\repository\com\google\zxing\javase\3.3.0\javase-3.3.0.jar;C:\Users\Admin\.m2\repository\com\beust\jcommander\1.48\jcommander-1.48.jar;C:\Users\Admin\.m2\repository\com\github\jai-imageio\jai-imageio-core\1.3.1\jai-imageio-core-1.3.1.jar;C:\Users\Admin\.m2\repository\org\apache\zookeeper\zookeeper\3.4.8\zookeeper-3.4.8.jar;C:\Users\Admin\.m2\repository\log4j\log4j\1.2.16\log4j-1.2.16.jar;C:\Users\Admin\.m2\repository\jline\jline\0.9.94\jline-0.9.94.jar;C:\Users\Admin\.m2\repository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;C:\Users\Admin\.m2\repository\org\apache\curator\curator-recipes\2.11.1\curator-recipes-2.11.1.jar;C:\Users\Admin\.m2\repository\org\apache\curator\curator-framework\2.11.1\curator-framework-2.11.1.jar;C:\Users\Admin\.m2\repository\org\apache\curator\curator-client\2.11.1\curator-client-2.11.1.jar;C:\Users\Admin\.m2\repository\org\testng\testng\6.10\testng-6.10.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ace-common\1.0-SNAPSHOT\ace-common-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\commons-io\commons-io\1.3.2\commons-io-1.3.2.jar;C:\Users\Admin\.m2\repository\tk\mybatis\mapper\3.4.0\mapper-3.4.0.jar;C:\Users\Admin\.m2\repository\javax\persistence\persistence-api\1.0\persistence-api-1.0.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-beans\5.1.9.RELEASE\spring-beans-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\com\github\pagehelper\pagehelper\5.0.3\pagehelper-5.0.3.jar;C:\Users\Admin\.m2\repository\com\github\jsqlparser\jsqlparser\1.0\jsqlparser-1.0.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-web\5.1.9.RELEASE\spring-web-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\io\jsonwebtoken\jjwt\0.7.0\jjwt-0.7.0.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.9.3\jackson-databind-2.9.9.3.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.9\jackson-core-2.9.9.jar;C:\Users\Admin\.m2\repository\joda-time\joda-time\2.10.3\joda-time-2.10.3.jar;C:\Users\Admin\.m2\repository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;C:\Users\Admin\.m2\repository\de\schlichtherle\truelicense\truelicense-core\1.32\truelicense-core-1.32.jar;C:\Users\Admin\.m2\repository\de\schlichtherle\truelicense\truelicense-xml\1.32\truelicense-xml-1.32.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ace-core\4.0\ace-core-4.0.jar;C:\Users\Admin\.m2\repository\org\mortbay\jetty\servlet-api\3.0.20100224\servlet-api-3.0.20100224.jar;C:\Users\Admin\.m2\repository\commons-httpclient\commons-httpclient\3.1\commons-httpclient-3.1.jar;C:\Users\Admin\.m2\repository\commons-logging\commons-logging\1.0.4\commons-logging-1.0.4.jar;C:\Users\Admin\.m2\repository\com\google\guava\guava\20.0\guava-20.0.jar;C:\Users\Admin\.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\Admin\.m2\repository\org\modelmapper\modelmapper\1.1.2\modelmapper-1.1.2.jar;C:\Users\Admin\.m2\repository\cn\hutool\hutool-all\4.1.9\hutool-all-4.1.9.jar;C:\Users\Admin\.m2\repository\com\baomidou\mybatis-plus\2.3\mybatis-plus-2.3.jar;C:\Users\Admin\.m2\repository\com\baomidou\mybatis-plus-support\2.3\mybatis-plus-support-2.3.jar;C:\Users\Admin\.m2\repository\com\baomidou\mybatis-plus-core\2.3\mybatis-plus-core-2.3.jar;C:\Users\Admin\.m2\repository\org\mybatis\mybatis-spring\1.3.2\mybatis-spring-1.3.2.jar;C:\Users\Admin\.m2\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;C:\Users\Admin\.m2\repository\com\baomidou\mybatis-plus-generate\2.3\mybatis-plus-generate-2.3.jar;C:\Users\Admin\.m2\repository\org\freemarker\freemarker\2.3.29\freemarker-2.3.29.jar;C:\Users\Admin\.m2\repository\cn\afterturn\easypoi-spring-boot-starter\3.2.0\easypoi-spring-boot-starter-3.2.0.jar;C:\Users\Admin\.m2\repository\cn\afterturn\easypoi-web\3.2.0\easypoi-web-3.2.0.jar;C:\Users\Admin\.m2\repository\cn\afterturn\easypoi-base\3.2.0\easypoi-base-3.2.0.jar;C:\Users\Admin\.m2\repository\org\apache\poi\poi-ooxml\3.15\poi-ooxml-3.15.jar;C:\Users\Admin\.m2\repository\com\github\virtuald\curvesapi\1.04\curvesapi-1.04.jar;C:\Users\Admin\.m2\repository\org\apache\poi\poi-ooxml-schemas\3.15\poi-ooxml-schemas-3.15.jar;C:\Users\Admin\.m2\repository\cn\afterturn\easypoi-annotation\3.2.0\easypoi-annotation-3.2.0.jar;C:\Users\Admin\.m2\repository\org\apache\poi\poi-scratchpad\3.15\poi-scratchpad-3.15.jar;C:\Users\Admin\.m2\repository\org\apache\poi\poi\3.15\poi-3.15.jar;C:\Users\Admin\.m2\repository\org\apache\commons\commons-collections4\4.1\commons-collections4-4.1.jar;C:\Users\Admin\.m2\repository\org\apache\poi\ooxml-schemas\1.3\ooxml-schemas-1.3.jar;C:\Users\Admin\.m2\repository\org\apache\xmlbeans\xmlbeans\2.3.0\xmlbeans-2.3.0.jar;C:\Users\Admin\.m2\repository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;C:\Users\Admin\.m2\repository\org\springframework\data\spring-data-redis\2.1.10.RELEASE\spring-data-redis-2.1.10.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\data\spring-data-keyvalue\2.1.10.RELEASE\spring-data-keyvalue-2.1.10.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\data\spring-data-commons\2.1.10.RELEASE\spring-data-commons-2.1.10.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-tx\5.1.9.RELEASE\spring-tx-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-oxm\5.1.9.RELEASE\spring-oxm-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-aop\5.1.9.RELEASE\spring-aop-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-context-support\5.1.9.RELEASE\spring-context-support-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\slf4j\slf4j-api\1.7.28\slf4j-api-1.7.28.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.1.8.RELEASE\spring-boot-starter-jdbc-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter\2.1.8.RELEASE\spring-boot-starter-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot\2.1.8.RELEASE\spring-boot-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.1.8.RELEASE\spring-boot-starter-logging-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\Admin\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\Admin\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\Users\Admin\.m2\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\Users\Admin\.m2\repository\org\slf4j\jul-to-slf4j\1.7.28\jul-to-slf4j-1.7.28.jar;C:\Users\Admin\.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\Admin\.m2\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\Users\Admin\.m2\repository\com\zaxxer\HikariCP\3.2.0\HikariCP-3.2.0.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-jdbc\5.1.9.RELEASE\spring-jdbc-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-undertow\2.1.8.RELEASE\spring-boot-starter-undertow-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\io\undertow\undertow-core\2.0.26.Final\undertow-core-2.0.26.Final.jar;C:\Users\Admin\.m2\repository\org\jboss\logging\jboss-logging\3.3.3.Final\jboss-logging-3.3.3.Final.jar;C:\Users\Admin\.m2\repository\org\jboss\xnio\xnio-api\3.3.8.Final\xnio-api-3.3.8.Final.jar;C:\Users\Admin\.m2\repository\org\jboss\xnio\xnio-nio\3.3.8.Final\xnio-nio-3.3.8.Final.jar;C:\Users\Admin\.m2\repository\io\undertow\undertow-servlet\2.0.26.Final\undertow-servlet-2.0.26.Final.jar;C:\Users\Admin\.m2\repository\org\jboss\spec\javax\annotation\jboss-annotations-api_1.2_spec\1.0.2.Final\jboss-annotations-api_1.2_spec-1.0.2.Final.jar;C:\Users\Admin\.m2\repository\io\undertow\undertow-websockets-jsr\2.0.26.Final\undertow-websockets-jsr-2.0.26.Final.jar;C:\Users\Admin\.m2\repository\org\jboss\spec\javax\websocket\jboss-websocket-api_1.1_spec\1.1.4.Final\jboss-websocket-api_1.1_spec-1.1.4.Final.jar;C:\Users\Admin\.m2\repository\org\glassfish\javax.el\3.0.0\javax.el-3.0.0.jar;C:\Users\Admin\.m2\repository\de\codecentric\spring-boot-admin-starter-client\1.3.2\spring-boot-admin-starter-client-1.3.2.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.1.8.RELEASE\spring-boot-starter-web-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.1.8.RELEASE\spring-boot-starter-json-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.9\jackson-datatype-jdk8-2.9.9.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.9\jackson-module-parameter-names-2.9.9.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.1.8.RELEASE\spring-boot-starter-tomcat-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.24\tomcat-embed-core-9.0.24.jar;C:\Users\Admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.24\tomcat-embed-el-9.0.24.jar;C:\Users\Admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.24\tomcat-embed-websocket-9.0.24.jar;C:\Users\Admin\.m2\repository\org\hibernate\validator\hibernate-validator\6.0.17.Final\hibernate-validator-6.0.17.Final.jar;C:\Users\Admin\.m2\repository\org\jolokia\jolokia-core\1.6.2\jolokia-core-1.6.2.jar;C:\Users\Admin\.m2\repository\com\googlecode\json-simple\json-simple\1.1.1\json-simple-1.1.1.jar;C:\Users\Admin\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Admin\.m2\repository\net\bytebuddy\byte-buddy\1.9.16\byte-buddy-1.9.16.jar;C:\Users\Admin\.m2\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;C:\Users\Admin\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-core\5.1.9.RELEASE\spring-core-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-jcl\5.1.9.RELEASE\spring-jcl-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-actuator\2.1.8.RELEASE\spring-boot-starter-actuator-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-actuator-autoconfigure\2.1.8.RELEASE\spring-boot-actuator-autoconfigure-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-actuator\2.1.8.RELEASE\spring-boot-actuator-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-context\5.1.9.RELEASE\spring-context-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.9\jackson-datatype-jsr310-2.9.9.jar;C:\Users\Admin\.m2\repository\io\micrometer\micrometer-core\1.1.6\micrometer-core-1.1.6.jar;C:\Users\Admin\.m2\repository\org\hdrhistogram\HdrHistogram\2.1.9\HdrHistogram-2.1.9.jar;C:\Users\Admin\.m2\repository\org\latencyutils\LatencyUtils\2.0.3\LatencyUtils-2.0.3.jar;C:\Users\Admin\.m2\repository\com\alibaba\druid-spring-boot-starter\1.1.0\druid-spring-boot-starter-1.1.0.jar;C:\Users\Admin\.m2\repository\com\alibaba\druid\1.1.0\druid-1.1.0.jar;C:\Program Files\Java\jdk1.8.0_161\lib\jconsole.jar;C:\Program Files\Java\jdk1.8.0_161\lib\tools.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.8.RELEASE\spring-boot-autoconfigure-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\mysql\mysql-connector-java\8.0.17\mysql-connector-java-8.0.17.jar;C:\Users\Admin\.m2\repository\com\spring4all\spring-boot-starter-swagger\1.5.1.RELEASE\spring-boot-starter-swagger-1.5.1.RELEASE.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-swagger-ui\2.7.0\springfox-swagger-ui-2.7.0.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-spring-web\2.7.0\springfox-spring-web-2.7.0.jar;C:\Users\Admin\.m2\repository\org\reflections\reflections\0.9.11\reflections-0.9.11.jar;C:\Users\Admin\.m2\repository\org\javassist\javassist\3.21.0-GA\javassist-3.21.0-GA.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-swagger2\2.7.0\springfox-swagger2-2.7.0.jar;C:\Users\Admin\.m2\repository\io\swagger\swagger-annotations\1.5.13\swagger-annotations-1.5.13.jar;C:\Users\Admin\.m2\repository\io\swagger\swagger-models\1.5.13\swagger-models-1.5.13.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-spi\2.7.0\springfox-spi-2.7.0.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-core\2.7.0\springfox-core-2.7.0.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-schema\2.7.0\springfox-schema-2.7.0.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-swagger-common\2.7.0\springfox-swagger-common-2.7.0.jar;C:\Users\Admin\.m2\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\Users\Admin\.m2\repository\org\springframework\plugin\spring-plugin-core\1.2.0.RELEASE\spring-plugin-core-1.2.0.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\plugin\spring-plugin-metadata\1.2.0.RELEASE\spring-plugin-metadata-1.2.0.RELEASE.jar;C:\Users\Admin\.m2\repository\org\mapstruct\mapstruct\1.1.0.Final\mapstruct-1.1.0.Final.jar;C:\Users\Admin\.m2\repository\io\springfox\springfox-bean-validators\2.7.0\springfox-bean-validators-2.7.0.jar;C:\Users\Admin\.m2\repository\org\apache\commons\commons-lang3\3.4\commons-lang3-3.4.jar;C:\Users\Admin\.m2\repository\com\alibaba\fastjson\1.2.33\fastjson-1.2.33.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ace-auth-client\1.0-SNAPSHOT\ace-auth-client-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-data-redis\2.1.8.RELEASE\spring-boot-starter-data-redis-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\io\lettuce\lettuce-core\5.1.8.RELEASE\lettuce-core-5.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\io\netty\netty-common\4.1.39.Final\netty-common-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\netty\netty-handler\4.1.39.Final\netty-handler-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\netty\netty-buffer\4.1.39.Final\netty-buffer-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\netty\netty-codec\4.1.39.Final\netty-codec-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\netty\netty-transport\4.1.39.Final\netty-transport-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\netty\netty-resolver\4.1.39.Final\netty-resolver-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\io\projectreactor\reactor-core\3.2.12.RELEASE\reactor-core-3.2.12.RELEASE.jar;C:\Users\Admin\.m2\repository\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar;C:\Users\Admin\.m2\repository\io\github\openfeign\feign-okhttp\9.5.0\feign-okhttp-9.5.0.jar;C:\Users\Admin\.m2\repository\io\github\openfeign\feign-core\9.5.0\feign-core-9.5.0.jar;C:\Users\Admin\.m2\repository\org\jvnet\animal-sniffer-annotation\1.0\animal-sniffer-annotation-1.0.jar;C:\Users\Admin\.m2\repository\com\qiniu\qiniu-java-sdk\7.2.25\qiniu-java-sdk-7.2.25.jar;C:\Users\Admin\.m2\repository\com\squareup\okhttp3\okhttp\3.14.2\okhttp-3.14.2.jar;C:\Users\Admin\.m2\repository\com\squareup\okio\okio\1.17.2\okio-1.17.2.jar;C:\Users\Admin\.m2\repository\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-core\1.0-SNAPSHOT\ms-erp-core-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-webmvc\5.1.9.RELEASE\spring-webmvc-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-expression\5.1.9.RELEASE\spring-expression-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-common-admin-api\1.0-SNAPSHOT\ms-common-admin-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\org\apache\httpcomponents\httpcore\4.4.12\httpcore-4.4.12.jar;C:\Users\Admin\.m2\repository\org\apache\httpcomponents\httpclient\4.5.9\httpclient-4.5.9.jar;C:\Users\Admin\.m2\repository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;C:\Users\Admin\.m2\repository\org\springframework\boot\spring-boot-starter-amqp\2.0.6.RELEASE\spring-boot-starter-amqp-2.0.6.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\spring-messaging\5.1.9.RELEASE\spring-messaging-5.1.9.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\amqp\spring-rabbit\2.1.8.RELEASE\spring-rabbit-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\com\rabbitmq\amqp-client\5.4.3\amqp-client-5.4.3.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-mall-api\1.0-SNAPSHOT\ms-erp-mall-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\org\springframework\amqp\spring-amqp\2.1.8.RELEASE\spring-amqp-2.1.8.RELEASE.jar;C:\Users\Admin\.m2\repository\org\springframework\retry\spring-retry\1.2.4.RELEASE\spring-retry-1.2.4.RELEASE.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-wms-api\1.0-SNAPSHOT\ms-erp-wms-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-crm-api\1.0-SNAPSHOT\ms-erp-crm-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-sales-api\1.0-SNAPSHOT\ms-erp-sales-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-transaction\1.0-SNAPSHOT\ms-erp-transaction-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\meishi\myy\ms-erp-financial-api\1.0-SNAPSHOT\ms-erp-financial-api-1.0-SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\github\wxiaoqi\transaction-springcloud\4.0.3.SNAPSHOT\transaction-springcloud-4.0.3.SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\github\wxiaoqi\tx-client\4.0.3.SNAPSHOT\tx-client-4.0.3.SNAPSHOT.jar;C:\Users\Admin\.m2\repository\com\github\1991wangliang\lorne_core\1.0.0\lorne_core-1.0.0.jar;C:\Users\Admin\.m2\repository\com\github\1991wangliang\lorne_exception\1.0.0.RELEASE\lorne_exception-1.0.0.RELEASE.jar;C:\Users\Admin\.m2\repository\commons-fileupload\commons-fileupload\1.3.1\commons-fileupload-1.3.1.jar;C:\Users\Admin\.m2\repository\commons-beanutils\commons-beanutils\1.7.0\commons-beanutils-1.7.0.jar;C:\Users\Admin\.m2\repository\commons-collections\commons-collections\3.2.1\commons-collections-3.2.1.jar;C:\Users\Admin\.m2\repository\commons-dbcp\commons-dbcp\1.4\commons-dbcp-1.4.jar;C:\Users\Admin\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;C:\Users\Admin\.m2\repository\commons-pool\commons-pool\1.6\commons-pool-1.6.jar;C:\Users\Admin\.m2\repository\commons-dbutils\commons-dbutils\1.6\commons-dbutils-1.6.jar;C:\Users\Admin\.m2\repository\commons-configuration\commons-configuration\1.10\commons-configuration-1.10.jar;C:\Users\Admin\.m2\repository\org\apache\httpcomponents\httpmime\4.5.9\httpmime-4.5.9.jar;C:\Users\Admin\.m2\repository\org\apache\axis\axis\1.4\axis-1.4.jar;C:\Users\Admin\.m2\repository\io\netty\netty-all\4.1.39.Final\netty-all-4.1.39.Final.jar;C:\Users\Admin\.m2\repository\org\aspectj\aspectjweaver\1.9.4\aspectjweaver-1.9.4.jar;C:\Users\Admin\.m2\repository\org\aspectj\aspectjrt\1.9.4\aspectjrt-1.9.4.jar;C:\Users\Admin\.m2\repository\com\caucho\hessian\4.0.38\hessian-4.0.38.jar;C:\Users\Admin\.m2\repository\com\dyuproject\protostuff\protostuff-core\1.1.3\protostuff-core-1.1.3.jar;C:\Users\Admin\.m2\repository\com\dyuproject\protostuff\protostuff-api\1.1.3\protostuff-api-1.1.3.jar;C:\Users\Admin\.m2\repository\com\dyuproject\protostuff\protostuff-runtime\1.1.3\protostuff-runtime-1.1.3.jar;C:\Users\Admin\.m2\repository\com\dyuproject\protostuff\protostuff-collectionschema\1.1.3\protostuff-collectionschema-1.1.3.jar;C:\Users\Admin\.m2\repository\com\esotericsoftware\kryo-shaded\4.0.0\kryo-shaded-4.0.0.jar;C:\Users\Admin\.m2\repository\com\esotericsoftware\minlog\1.3.0\minlog-1.3.0.jar;C:\Users\Admin\.m2\repository\com\github\wxiaoqi\tx-plugins-db\4.0.3.SNAPSHOT\tx-plugins-db-4.0.3.SNAPSHOT.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.5\lib\idea_rt.jar

在这里插入图片描述原生加载器对应加载的主目录
实例 根类加载器加载类
当我们把对应在classpath下的.class文件放到根类加载器能加载的目录下时
在这里插入图片描述
在这里插入图片描述此时

public class MyTest18_1 {

    public static void main(String[] args) throws ClassNotFoundException {
        Test16 loader1 = new Test16("loader1");
        loader1.setPath("E:\\cx\\");

        Class<?> clasz = loader1.loadClass("com.example.demo.com.jvm.Test1");
        System.out.println("class: " + clasz.hashCode());
        System.out.println("class loader: "+ clasz.getClassLoader());
    }
}

打印结果如下

class: 515132998
class loader: null  显示根类加载加载

实例 扩展类加载器运用

public class MyTest19 {
    public static void main(String[] args) {
        AESKeyGenerator aesKeyGenerator = new AESKeyGenerator();

        System.out.println(aesKeyGenerator.getClass().getClassLoader());
        System.out.println(MyTest19.class.getClassLoader());
    }
}

sun.misc.Launcher$ExtClassLoader@1175e2db
sun.misc.Launcher$AppClassLoader@18b4aac2

在这里插入图片描述当把扩展类加载器指定为当前目录 程序运行异常 显然当前路径下不存在AESKeyGenerator 类的 所以是在指定路径下加载的AESKeyGenerator.class

实例3
新增一个MyPerson类

public class MyPerson {
    private MyPerson myPerson;

    public void setMyPerson(Object myPerson) {
        this.myPerson = (MyPerson)myPerson;
    }
}

public class MyTest20 {

    public static void main(String[] args) throws Exception {
        Test16 loader1 = new Test16("loader1");
        Test16 loader2 = new Test16("loader2");

        Class<?> aClass1 = loader1.loadClass("com.example.demo.com.jvm.MyPerson");
        Class<?> aClass2 = loader2.loadClass("com.example.demo.com.jvm.MyPerson");//new了两次 两个根本不相同的类加载器

        System.out.println(aClass1);
        System.out.println(aClass2);//class com.example.demo.com.jvm.MyPerson 此时只是类型不是对象 对象会生成hashcode

        System.out.println(aClass1 == aClass2); //两个都是系统类加载器加载的第一个加载完第二个请求加载发现存在该类已经被加载直接拿来用

        Object o1 = aClass1.newInstance();
        Object o2 = aClass2.newInstance();

        Method method = aClass1.getMethod("setMyPerson", Object.class);
        //获取o1的setMyPerson方法将o2传进去
        method.invoke(o1, o2);

    }
}
两个都是系统类加载器加载的第一个加载完第二个请求加载发现存在该类已经被加载直接拿来用 相同的命名空间
class com.example.demo.com.jvm.MyPerson
class com.example.demo.com.jvm.MyPerson
true

命名空间详解

基于上例修改
此时将classpath下的Myperson.class删除


/*
     类加载器的双亲委托机制模型的好处:

     1.可以确保Java核心库的类型安全:所有的Java应用都至少会引用java.lang.Object类,也就是说在运行期,java.lang.Object这个类
     会被加载到Java虚拟机中; 如果这个加载过程是由Jva应用自己的类加载器所完成的,那么很有可能就会在JVM中存在多个版本的java.lang.Object类
     而且这些类之间还是不兼容的,相互不可见的(正式命名空间在发挥着作用)。
     借助于双亲委托机制,Java核心类库中的类的加载工作都是由启动类加载器来统一完成的,从而确保了Java应用所使用都是同一个版本的Java核心类库,
     他们之间是相互兼容的

     2.可以确保Java核心类库所提供的的类不会被自定义的类所替代

     3.不同的类加载器可以为相同名称(binary name 二进制名)的类创建额外的命名空间。相同名称的类可以存在Java虚拟机中,只需要用不同的类加载器来加载
     他们即可。不同的类加载器所加载的类之间是不兼容的,这就相当于在java虚拟机内部创建了一个又一个相互隔离的Java类空间,这类技术在很多框架中都得到了实际应用
 */

public class MyTest21 {

    public static void main(String[] args) throws Exception {
        Test16 loader1 = new Test16("loader1");
        Test16 loader2 = new Test16("loader2");

        loader1.setPath("E:\\cx\\");
        loader2.setPath("E:\\cx\\");

        //当classpash下找不到对应的.class文件会去加载自己对应的类加载器 所以loader1和loader2本质上是没有联系的,在内存中两个不同的命名空间
        Class<?> aClass1 = loader1.loadClass("com.example.demo.com.jvm.MyPerson");
        Class<?> aClass2 = loader2.loadClass("com.example.demo.com.jvm.MyPerson");
//        System.out.println(aClass1);
//        System.out.println(aClass2);//class com.example.demo.com.jvm.MyPerson 此时只是类型不是对象 对象会生成hashcode

        System.out.println(aClass1 == aClass2);

        Object o1 = aClass1.newInstance();
        Object o2 = aClass2.newInstance();

        Method method = aClass1.getMethod("setMyPerson", Object.class);
        //获取o1的setMyPerson方法将o2传进去
        method.invoke(o1, o2);

    }
}

打印结果

findClass invoked:com.example.demo.com.jvm.MyPerson
class loader name: loader1
findClass invoked:com.example.demo.com.jvm.MyPerson
class loader name: loader2


当classpash下找不到对应的.class文件会去加载自己对应的类加载器 
所以loader1和loader2本质上是没有联系的,JVM在内存开辟中两个不同的命名空间
false

两个相互独立的命名空间不可见 包名类名相同也会抛异常了
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.example.demo.com.jvm.MyTest21.main(MyTest21.java:27)
Caused by: java.lang.ClassCastException: com.example.demo.com.jvm.MyPerson cannot be cast to com.example.demo.com.jvm.MyPerson
	at com.example.demo.com.jvm.MyPerson.setMyPerson(MyPerson.java:7)
	... 5 more

JVM在内存开辟中两个不同的命名空间下面结论第四条
描述在这里插入图片描述
同一个命名空间内的类时相互可见,但是不一定可以相互使用这个是根据修饰符来决定的 这是两个不同的概念,子加载可以看到父加载的命名空间(类似继承)自定义可以看到父以上的命名空间

运行期,一个java类是由该类的完全限定名(binary name,二进制名) 和用于加载该类的定义类加载器(defining loader)所共同决定的。如果同样名字(即相同的完全限定名)的类是由两个不同的加载器所加载,那么这些类就是不同的,即便.class文件的字节码完全一样,并且从相同的位置加载亦如此。

类加载器的双亲委托机制模型的好处:

1.可以确保Java核心库的类型安全:所有的Java应用都至少会引用java.lang.Object类,也就是说在运行期,java.lang.Object这个类会被加载到Java虚拟机中; 如果这个加载过程是由Java应用自己的(自定义)类加载器所完成的,那么很有可能就会在JVM中存在多个版本的java.lang.Object类;而且这些类之间还是不兼容的,相互不可见的(正式命名空间在发挥着作用)。借助于双亲委托机制,Java核心类库中的类的加载工作都是由启动类加载器来统一完成的,从而确保了Java应用所使用都是同一个版本的Java核心类库, 他们之间是相互兼容
在这里插入图片描述
2.可以确保Java核心类库所提供的的类不会被自定义的类所替代

3…不同的类加载器可以为相同名称(binary name 二进制名)的类创建额外的命名空间。相同名称的类可以存在Java虚拟机中,只需要用不同的类加载器类似于loader1和loader2之间不存在直接或间接的父子关系)来加载他们即可。不同的类加载器所加载的类之间是不兼容的,这就相当于在java虚拟机内部创建了一个又一个相互隔离的Java类空间(不同的命名空间),这类技术在很多框架中都得到了实际应用

扩展类加载器分析


/*
    扩展类加载器加载路径下jar包的形式加载.class类不是直接加载.class
 */

public class MyTest22 {

    static {
        System.out.println("MyTest22 initializer");
    }

    public static void main(String[] args) {
        System.out.println(MyTest22.class.getClassLoader());
        System.out.println(Test1.class.getClassLoader());
    }
}

此时打印的是
java -Djava.ext.dirs=./ 类的全路径 将Djava.ext.dirs目录下检索 类的全路径 改为从当前目录下
在这里插入图片描述
当打成jar包时
在这里插入图片描述打印结果
在这里插入图片描述

原创文章 39 获赞 6 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42261668/article/details/102476915