当前位置: 首页 > 后端技术 > Java

类卸载

时间:2023-04-01 19:45:59 Java

packagestudy;importjava.net.URL;importjava.net.URLClassLoader;/*Java虚拟机自带的类加载器加载的类永远不会卸载,Java虚拟机自带的类加载器机器包括一个根类加载器,一个扩展类加载器和一个系统类加载器。  Java虚拟机本身会一直引用这些类加载器,而这些类加载器又会一直引用自己加载的类的Class对象,所以这些Class对象总是可以访问的。  由用户定义的类加载器加载的类可以被卸载。jvm参数-verbose:class可以看到类的加载卸载信息*//*卸载类满足的条件1.类的所有实例被回收2.类类没有引用3.加载器该类的实例被回收*/线程.睡眠(5000);系统.gc();线程.睡眠(5000);(){/*当路径不以'/'开头时,默认从该类所在的包中获取资源;当路径以'/'开头时,从ClassPath的根部获取;this.getClass().getResource("").getPath();*///这个路径<=appClassLoader负责的路径,因为双亲委托的机制Stringpath="/D:/gitHome/asmStudy/target/classes/";try{//必须在这里添加file:表示协议ClassLoaderloader1=newURLClassLoader(newURL[]{newURL("file:"+path)});//类名必须写全Classt=loader1.loadClass("instrumentation.TransClass");t=空;装载机1=空;}catch(Exceptione){e.printStackTrace();}}}当类加载器覆盖finalizepackagestudy;importjava.io.IOException;importjava.nio.file.Files;importjava.nio.file.Paths;publicclassMyClassLouderextendsClassLoader{publicstaticvoidmain(String[]args)throwsException{字符串路径="D:\\Users\\YEZHENGWU839\\Desktop\\xiaoxi\\";MyClassLouderother=newMyClassLouder(path,"other");Class.forName("MethodAccessor.TestLoad",true,other);其他=空;线程.睡眠(5000);系统.gc();线程.睡眠(5000);//第一次gc无法卸载类,因为finalize线程的优先级比较低,所以在回收的时候//other的finalize对象还没有被finalize线程清理掉//所以other没有被回收,所以类无法卸载System.out.println("第一次gc结束,第二次开始");系统.gc();线程.睡眠(5000);私有字符串类路径;私有字符串名称;//覆盖finalize方法一般不会影响gc@Overrideprotectedvoidfinalize()throwsThrowable{System.out.println("MyClassLoaderfinalize");}publicMyClassLouder(Stringclasspath,Stringname){this.classpath=classpath;this.name=名称;}publicMyClassLouder(Stringclasspath,Stringname,ClassLoaderparent){super(parent);this.classpath=类路径;this.name=名称;}@OverrideprotectedClassfindClass(Stringname)throwsClassNotFoundException{try{byte[]bin=Files.readAllBytes(Paths.get(classpath+name.replace(".","/")+".class"));返回defineClass(bin,0,bin.length);}catch(IOExceptione){thrownewClassNotFoundException();}}}