JVM 類載入器_2
阿新 • • 發佈:2018-12-11
名稱空間深度解析
直接先上例子
package com.ssy.jvm.classloader;
import java.lang.reflect.Method;
public class MyTest21 {
public static void main(String[] args) throws Exception {
MyFirstClassLoader loader1 = new MyFirstClassLoader("loader1");
MyFirstClassLoader loader2 = new MyFirstClassLoader ("loader2");
loader1.setPath("/Users/ddcc/Desktop");
loader2.setPath("/Users/ddcc/Desktop");
Class<?> clazz1 = loader1.loadClass("com.ssy.jvm.classloader.MyPerson");
Class<?> clazz2 = loader2.loadClass("com.ssy.jvm.classloader.MyPerson");
System.out.println (clazz1 == clazz2);
Object object1 = clazz1.newInstance();
Object object2 = clazz2.newInstance();
Method method = clazz1.getMethod("setMyPerson", Object.class);
method.invoke(object1, object2);
}
}
package com.ssy.jvm.classloader;
public class MyPerson {
private MyPerson myPerson;
public void setMyPerson(Object myPerson) {
this.myPerson = (MyPerson) myPerson;
}
}
我們先將classpath中的MyPerson.class檔案保留
結果:
true
解析:
經過上一節類載入器的講解,我們知道,類載入的過程是通過雙親委託機制來完成的。loader1和loader2都會交由它的父載入器–系統類載入器 去進行載入,而很明顯,系統類載入器可以載入MyPerson類。當loader1交由系統類載入器載入後,loader2再交由系統類載入器載入時,發現這個類已經被載入了,那麼會直接返回這個類的Class物件,所以結果為True。
我們現在將classpath中的MyPerson.class刪除,在Desktop上放這個檔案。
結果
findClass invoked: com.ssy.jvm.classloader.MyPerson
class loader name: loader1
findClass invoked: com.ssy.jvm.classloader.MyPerson
class loader name: loader2
false
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ssy.jvm.classloader.MyTest21.main(MyTest21.java:22)
Caused by: java.lang.ClassCastException: com.ssy.jvm.classloader.MyPerson cannot be cast to com.ssy.jvm.classloader.MyPerson
at com.ssy.jvm.classloader.MyPerson.setMyPerson(MyPerson.java:7)
... 5 more
分析
這個結果就非常好玩了。首先打印出false,其次,丟擲了異常。我們分別來解釋。 loader1和loader2是沒有直接或間接父子關係的兩個載入器。所以它們在各自的名稱空間內。
同一個名稱空間內的類是相互可見的 子載入器的名稱空間包含父載入器的名稱空間,因此子載入器載入的類能看到父載入器所載入的類 父載入器所載入的類看不到子載入器所載入的類。 如果兩個載入器之間沒有直接或者間接的父子關係,那麼相互不可見
所以loader1載入的Class物件和loader2載入的Class物件是相互不可見的。由此,它們new出來的物件也是相互不可見的。當用反射呼叫方法將loader2載入的Class物件所對應的類的例項傳入時,轉換為loader1載入的Class物件所對應的類中,就會丟擲類轉換異常。
單獨看java.lang.ClassCastException: com.ssy.jvm.classloader.MyPerson cannot be cast to com.ssy.jvm.classloader.MyPerson
這個異常的時候,真的是不知所云,哈哈哈。。