2回复
3年前
这个 ThreadLocal 怎么防止类加载器被回收?
我想搞清楚 Threadlocal是怎样导致类加载器泄漏的,所以写了这些代码
public class Main {
public static void main(String... args) throws Exception {
loadClass();
while (true) {
System.gc();
Thread.sleep(1000);
}
}
private static void loadClass() throws Exception {
URL url = Main.class.getProtectionDomain()
.getCodeSource()
.getLocation();
MyCustomClassLoader cl = new MyCustomClassLoader(url);
Class<?> clazz = cl.loadClass("com.test.Foo");
clazz.newInstance();
cl = null;
}
}
class MyCustomClassLoader extends URLClassLoader {
public MyCustomClassLoader(URL... urls) {
super(urls, null);
}
@Override
protected void finalize() {
System.out.println("*** CustomClassLoader finalized!");
}
}
Foo.java
public class Foo {
private static final ThreadLocal<Bar> tl = new ThreadLocal<Bar>();
public Foo() {
Bar bar = new Bar();
tl.set(bar);
System.out.println("Test ClassLoader: " + this.getClass()
.getClassLoader());
}
@Override
protected void finalize() {
System.out.println(this + " finalized!");
}
}
Bar.java
public class Bar {
public Bar() {
System.out.println(this + " created");
System.out.println("Bar ClassLoader: " + this.getClass()
.getClassLoader());
}
@Override
public void finalize() {
System.out.println(this + " finalized");
}
}
我运行代码后,它显示未调用 MyCustomClassloader 和 Bar finalize,仅调用 Foo finalize。 但我把 Threadlocal 更改为 String 时,所有的 finalize 都会被调用。
public class Foo {
private static final ThreadLocal<String> tl = new ThreadLocal<String>();
public Foo() {
Bar bar = new Bar();
tl.set("some");
System.out.println("Test ClassLoader: " + this.getClass()
.getClassLoader());
}
有大佬能解释一下为什么在使用 ThreadLocal 作为 String 和 Bar 的时候会有区别吗?
1949 阅读