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(); } } }
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); } }
注释//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