遗忘海岸

江湖程序员 -Feiph(LM战士)

导航

java类加载器的一些测试

package classloader;

import java.lang.reflect.Method;

import org.junit.Test;

import com.example.Sample;


public class ClassIdentity {

    public static void main(String[] args) {
        
//        new ClassIdentity().testClassIdentity();
//        System.out.println("执行了吗");
        
        new ClassIdentity().testICalculator();
    }
    
    public void testICalculator(){
        
        String basicClassName = "com.example.CalculatorBasic";
        String advancedClassName = "com.example.CalculatorAdvanced";
        String classDataRootPath = "C:\\";
        FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
        
        try {
            Class<?> class1 = fscl1.loadClass(basicClassName);
            //下面这句会导致fscl1尝试加载在C:\下面加载classloader.ICalculator
            ICalculator calculator=(ICalculator)class1.newInstance();
            System.out.println(calculator.getVersion());
            System.out.println( ICalculator.class.getClassLoader());
            System.out.println( calculator.getClass().getClassLoader());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
    }
    @Test
    public void testClassIdentity() {
        String classDataRootPath = "C:\\";
        FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
        FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath);
        String className = "com.example.Sample";    
        try {
            Class<?> class1 = fscl1.loadClass(className);
            Object obj1 = class1.newInstance();

            Class<?> class2 = fscl2.loadClass(className);
            Object obj2 = class2.newInstance();
            
            System.out.println("不同加载器->" + class1.equals(class2));
            
            Class<?> c1=  this.getClass().getClassLoader().loadClass("classloader.Versioned");
            Class<?> c2=  this.getClass().getClassLoader().loadClass("classloader.Versioned");
            
            System.out.println("同一个->" + c1.equals(c2));
            
            Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class);
//            setSampleMethod.invoke(obj1, obj1);
//            setSampleMethod.invoke(obj1, obj1);
            System.out.println( Sample.class.getClassLoader());
            System.out.println( ClassIdentity.class.getClassLoader());
            System.out.println(obj1.getClass().getClassLoader() );
            Sample sample=(Sample)obj1; //无法将obj1转化成Sample,引用的类加载器不同
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}
View Code

testICalculator()输出:
这里com.example.CalculatorBasic
这里classloader.ICalculator
这里java.lang.Object
1.0
sun.misc.Launcher$AppClassLoader@105d88a
classloader.FileSystemClassLoader@76fba0

改写类加载器

package classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileSystemClassLoader extends ClassLoader {

    private String rootDir;

    public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }
 
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        else {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    private byte[] getClassData(String className) {
        String path = classNameToPath(className);
        try {
            InputStream ins = new FileInputStream(path);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bufferSize = 4096;
            byte[] buffer = new byte[bufferSize];
            int bytesNumRead = 0;
            while ((bytesNumRead = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesNumRead);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String classNameToPath(String className) {
        return rootDir + File.separatorChar
                + className.replace('.', File.separatorChar) + ".class";
    }
    
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
        System.out.println("这里" + name);
        if("java.lang.Object".equals(name)
           || "classloader.ICalculator".equals(name)        
                ){
            return super.loadClass(name, resolve);
        }
        
        return findClass(name);
    }
    
}
View Code

 
注释//Sample sample=(Sample)obj1; 后的输出:
这里com.example.Sample
这里java.lang.Object
这里com.example.Sample
这里java.lang.Object
不同加载器->false
同一个->true
sun.misc.Launcher$AppClassLoader@105d88a
sun.misc.Launcher$AppClassLoader@105d88a
classloader.FileSystemClassLoader@1866417

打开注释后的输出:


这里com.example.Sample
这里java.lang.Object
这里com.example.Sample
这里java.lang.Object
不同加载器->false
同一个->true
sun.misc.Launcher$AppClassLoader@105d88a
sun.misc.Launcher$AppClassLoader@105d88a
classloader.FileSystemClassLoader@1526e3
java.lang.ClassCastException: com.example.Sample cannot be cast to com.example.Sample

posted on 2013-07-03 15:18  遗忘海岸  阅读(595)  评论(0编辑  收藏  举报