共计 2099 个字符,预计需要花费 6 分钟才能阅读完成。
package study;
import java.net.URL;
import java.net.URLClassLoader;
/*
由 Java 虚拟机自带的类加载器所加载的类,在虚拟机的生命周期中,始终不会被卸载,Java 虚拟机自带的类加载器包含根类加载器、扩大类加载器和零碎类加载器。Java 虚拟机自身会始终援用这些类加载器,而这些类加载器则会始终援用它们所加载的类的 Class 对象,因而这些 Class 对象始终是可涉及的。由用户自定义的类加载器加载的类是能够被卸载的。jvm 参数 -verbose:class 即可看到类的加载和卸载信息
*/
/*
卸载类满足的条件
1、class 所有实例被回收
2、class 类没有别援用
3、class 的加载器实例被回收
*/
public class StudyMain {public static void main(String[] args) throws Exception {new StudyMain().solve();
Thread.sleep(5000);
System.gc();
Thread.sleep(5000);
}
public void solve() {
/*
path 不以’/' 结尾时,默认是从此类所在的包下取资源;path 以’/' 结尾时,则是从 ClassPath 根下获取;this.getClass().getResource("").getPath();
*/
// 这个门路 <= appClassLoader 所负责的门路,因为双亲委托的机制
String path = "/D:/gitHome/asmStudy/target/classes/";
try {
// 这里肯定要加 file: 示意协定
ClassLoader loader1 = new URLClassLoader(new URL[]{new URL("file:" + path)});
// 类名要写全
Class t = loader1.loadClass("instrumentation.TransClass");
t = null;
loader1 = null;
} catch (Exception e) {e.printStackTrace();
}
}
}
当类加载器重写了 finalize
package study;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class MyClassLouder extends ClassLoader {public static void main(String[] args) throws Exception {
String path = "D:\\Users\\YEZHENGWU839\\Desktop\\xiaoxi\\";
MyClassLouder other = new MyClassLouder(path, "other");
Class.forName("MethodAccessor.TestLoad", true, other);
other = null;
Thread.sleep(5000);
System.gc();
Thread.sleep(5000);
// 第一次 gc 卸载不掉类是因为 finalize 线程优先级比拟低 所以回收的时候
// other 的 finalize 对象还没有被 finalize 线程清理
// 所以 other 并没有回收,所以类也就卸载不了
System.out.println("第一次 gc 完结 第二次开始");
System.gc();
Thread.sleep(5000);
}
private String classpath;
private String name;
// 重写 finalize 办法 个别不重写这个 影响 gc
@Override
protected void finalize() throws Throwable {System.out.println("MyClassLoader finalize");
}
public MyClassLouder(String classpath, String name) {
this.classpath = classpath;
this.name = name;
}
public MyClassLouder(String classpath, String name, ClassLoader parent) {super(parent);
this.classpath = classpath;
this.name = name;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {byte[] bin = Files.readAllBytes(Paths.get(classpath + name.replace(".", "/") + ".class"));
return defineClass(bin, 0, bin.length);
} catch (IOException e) {throw new ClassNotFoundException();
}
}
}
正文完