前言
每一個類加載器都有各自的命名空間,命名空間是由該加載器及其所有父加載器所構成的,因此在每個類加載器中同一個class都是獨一無二的。
public class NameSpace {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = NameSpace.class.getClassLoader();
Class<?> aClass = classLoader.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
Class<?> bClass = classLoader.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
System.out.println(aClass.hashCode());
System.out.println(bClass.hashCode());
System.out.println(aClass == bClass);
}
}
不論load多少次,你都將會發現他們始終是同一份class對象。但是使用不同類加載器,或者同一個類加載器的不同實例,去加載同一個class,則會在堆內存和方法區會產生多個class對象。
不同類加載器加載同一個class
public class DiffClassLoader {
public static void main(String[] args) throws ClassNotFoundException {
MyClassloader myClassloader = new MyClassloader();
BrokerDelegateClassLoader brokerDelegateClassLoader = new BrokerDelegateClassLoader();
Class<?> clazzA = myClassloader.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
Class<?> clazzB = brokerDelegateClassLoader.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
System.out.println(clazzA.getClassLoader());
System.out.println(clazzB.getClassLoader());
System.out.println(clazzA.hashCode());
System.out.println(clazzB.hashCode());
System.out.println(clazzA == clazzB);
}
}
會生成兩個class實例。
相同類加載器加載同一個class
public class DoubleClassLoader {
public static void main(String[] args) throws ClassNotFoundException {
BrokerDelegateClassLoader myClassloaderA = new BrokerDelegateClassLoader();
BrokerDelegateClassLoader myClassloaderB = new BrokerDelegateClassLoader();
Class<?> clazzA = myClassloaderA.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
Class<?> clazzB = myClassloaderB.loadClass("fast.cloud.nacos.juc.classloader.HelloWorld");
System.out.println(clazzA.getClassLoader());
System.out.println(clazzB.getClassLoader());
System.out.println(clazzA.hashCode());
System.out.println(clazzB.hashCode());
System.out.println(clazzA == clazzB);
}
}
會生成兩個class實例。首先通過加載記錄表中的也就是緩存中的,查看該類是否已經被加載過了,如果加載過了,就不會重複加載了,否則將會認爲其實首次加載,也就是說同一個class實例在同一個類加載器命名空間之下是唯一的。
類的卸載
類的卸載需要滿足下面三個條件纔會被GC回收,也就是類被卸載。
- 該類所有的實例都已經被GC
- 加載該類的ClassLoader實例被回收
- 該類的class實例沒有在其他地方被引用。