运行时重新加载:ClassLoader.loadClass
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Class<?> aClass = contextClassLoader.loadClass("com.lls.base.media.service.api.config.Student"); Object o = aClass.newInstance(); if (o instanceof Student) { Student student = (Student) o; System.out.println(student.saySomeThing()); } System.out.println("stop..."); 利用idea compile Student类重新编译,后续在loadClass 可以实现模拟热加载 Class<?> afterClass = contextClassLoader.loadClass("com.lls.base.media.service.api.config.Student"); Object o1 = afterClass.newInstance(); Student student1 = (Student) o1; System.out.println(student1.saySomeThing());
hello
stop...
hello nihao
ClassLoader
// The classes loaded by this class loader. The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private final Vector<Class<?>> classes = new Vector<>();
使用vector 保存加载的类,保证不被gc掉
loadClass(String name)-》Class<?> loadClass(String name, boolean resolve) -》 URLClassLoader: Class<?> findClass(final String name)
![](https://i-blog.csdnimg.cn/blog_migrate/a0a920a386ab2ced427ee721a19009fa.png)
打印java.class.path 结果:包含Program Files\jdk\jre\lib 、maven的仓库 repo 中第三方jar包、
classpath 等价于 main/java + main/resources + 第三方jar包的根目录
C:\Program Files\Java\jdk1.8.0_202\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar;D:\lyr\aa\base-media-service-api\target\classes;D:\apache-maven-3.6.3\repo\org\apache\dubbo\dubbo\2.7.0\dubbo-2.7.0.jar;D:\apache-maven-3.6.3\repo\org\springframework\spring-context\4.3.16.RELEASE\spring-context-4.3.16.RELEASE.jar;D:\apache-maven-3.6.3\repo\org\springframework\spring-beans\4.3.16.RELEASE\spring-beans-4.3.16.RELEASE.jar;D:\apache-maven-3.6.3\repo\org\springframework\spring-expression\4.3.16.RELEASE\spring-expression-4.3.16.RELEASE.jar;D:\apache-maven-3.6.3\repo\org\javassist\javassist\3.20.0-GA\javassist-3.20.0-GA.jar;D:\apache-maven-3.6.3\repo\io\netty\netty-all\4.1.25.Final\netty-all-4.1.25.Final.jar;D:\apache-maven-3.6.3\repo\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;D:\apache-maven-3.6.3\repo\com\lls\common\cloud\module\base-media-base-infs\1.0.0-SNAPSHOT\base-media-base-infs-1.0.0-20190724.143215-98.jar;D:\apache-maven-3.6.3\repo\com\lls\common\cloud\module\base-common\1.3.1-SNAPSHOT\base-common-1.3.1-20210329.024137-43.jar;D:\apache-maven-3.6.3\repo\com\lls\common\cloud\module\base-jrc\2.0.0-ams-media-SNAPSHOT\base-jrc-2.0.0-ams-media-20191129.034243-1.jar;D:\apache-maven-3.6.3\repo\com\lls\framework\lls-mybatis-extra\2.1.0-SNAPSHOT\lls-mybatis-extra-2.1.0-20201230.023359-41.jar;D:\apache-maven-3.6.3\repo\org\projectlombok\lombok\1.18.2\lombok-1.18.2.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\lib\idea_rt.jarspringboot 启动话,String property = System.getProperty("java.class.path"); 会多出下列路径D:\lyr\new\ams-ast\ast-service\target\test-classes;D:\lyr\new\ams-ast\ast-service\target\classes;
加载的流程
![](https://i-blog.csdnimg.cn/blog_migrate/2d5fe5c4ebb52b30ead7a775624207d1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c0983e0380ce3a52d3b3f0bf9e218409.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1b02010435047e634371a3bccd9e8b09.png)
定义(解析resource)通过类名来读取 并定义 class
![](https://i-blog.csdnimg.cn/blog_migrate/2c1df904fd8e0612642bd93f64967e5b.png)
findLoadClass是netive 方法,已加载的类被jvm托管。卸载类需要卸载classLoader
![](https://i-blog.csdnimg.cn/blog_migrate/38e36a52695e241a41e7dbceef949218.png)
每个class类 就会有个属性 ClassLoader记录是哪个类加载器加载的
![](https://i-blog.csdnimg.cn/blog_migrate/2860096759e44b9d514290fcd9b2a259.png)
-
Class.forName() 里面用到的Reflection.getCallerClass() 和forName0都是native方法 ,initialize 值为true表示加载后会进行解释初始化(会执行静态代码块)
{
Reflection.getCallerClass() 如果需要时间 需要将class加到启动类加载器路径 在方法上需要加上注解
@CallerSensitive 否则会包异常
}
![](https://i-blog.csdnimg.cn/blog_migrate/e219c7cc574ad13f3d708a1a3e395133.png)