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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
2010-07-03 广告位管理系统---使用说明
2008-07-03 GridView 的一些使用技巧