1. 程式人生 > >類載入器[4]由不同ClassLoader物件載入的同名類屬於不同類

類載入器[4]由不同ClassLoader物件載入的同名類屬於不同類

由不同ClassLoader物件載入的同名類屬於不同的型別,不能相互轉化和相容。

新建一個工程NotSameClass。將如下程式碼,一份放入NoSameClass工程原始碼目錄下,一份編譯成.class放入D:\temp目錄下


執行如下程式碼,使用不同的類載入器載入同一個類(原始碼都一樣,不過一個來自bin目下的.class,一個來自D:\temp下的.class

 Java Code 

package com.bjsxt.test;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

publicclass Test {

    
publicstaticvoid main(String[] args) {
        
        
//先用應用類載入器載入HelloLoader
        HelloLoader object1=new HelloLoader();
        System.out.println(object1.getClass().getClassLoader());
        
        
//再用擴充套件類載入器載入HelloLoader
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        
try {
            
byte[] classBytes = loadClassBytes("com.bjsxt.test.HelloLoader");
            
            Method defineClassMethod = ClassLoader.
class.getDeclaredMethod("defineClass"byte[].classint.class
int.class);
            defineClassMethod.setAccessible(true);
            defineClassMethod.invoke(cl.getParent(), classBytes, 
0, classBytes.length);
            
            Class<?> clazz = cl.getParent().loadClass(
"com.bjsxt.test.HelloLoader");
            System.out.println(clazz.getClassLoader());
            
            
//兩個不同類的物件強制型別轉換            object1=(HelloLoader)clazz.newInstance();
            
        } 
catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
catch (SecurityException e) {
            e.printStackTrace();
        } 
catch (IllegalAccessException e) {
            e.printStackTrace();
        } 
catch (IllegalArgumentException e) {
            e.printStackTrace();
        } 
catch (InstantiationException e) {
            e.printStackTrace();
        } 
catch (NoSuchMethodException e) {
            e.printStackTrace();
        } 
catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        
    }
    
    
/**
     * 
將包名中的.替換成路徑分隔符,從D:/temp/目錄下查詢這個檔案,如果存在的話,將其讀取到位元組陣列
     * @param name
     * @return
     */
publicstaticbyte[] loadClassBytes(java.lang.String name) {
        
        
String path="D:/temp/"+name.replace(".""/")+".class";
        
        InputStream is=null;
        ByteArrayOutputStream baos=null;
        
        
try {
            is=
new FileInputStream(path);
            
            baos=
new ByteArrayOutputStream();
            
            
byte[] buffer=newbyte[1024];
            
            
int ret=0;
            
while((ret=is.read(buffer))!=-1){
                baos.write(buffer, 
0, ret);
            }
            
            
return baos.toByteArray();
            
        } 
catch (FileNotFoundException e) {
            e.printStackTrace();
        } 
catch (IOException e) {
            e.printStackTrace();
        }
finally{
            
try {
                
if(is!=null)
                    is.close();
                
                
if(baos!=null)
                    baos.close();
            } 
catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        
return null;
    }
}


並且,即便是同一類 類載入器,不同的物件加載出來的類也不是同一個類。