标签:com jdk als package 码流 public input 双亲委派模型 not
示例:
package com.classloader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class MyClassLoader extends ClassLoader { private static final String CLASS_PATH = System.getProperty("java.class.path"); // 编译生成的.class文件的bin目录 public MyClassLoader() { super(ClassLoader.getSystemClassLoader()); } @Override protected Class<?> findClass(String className) throws ClassNotFoundException { System.out.println("findClass ...."); byte[] b = loadClassFile(className); return super.defineClass(className, b, 0, b.length); } private byte[] loadClassFile(String className) { System.out.println("loadClassFile ...."); className = className.replace(".", "/"); File file = new File(CLASS_PATH + "/" + className + ".class"); try { FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b = 0; while ((b = fis.read()) != -1) { baos.write(b); } fis.close(); return baos.toByteArray(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
说明:这个示例中MyClassLoader这个类没有重写loadClass方法,因此调用loadClass方法实际调用的是父类的loadClass方法,即loadClass 实质上是使用了系统类加载器加载的,而调用 findClass 方法才是真正意义上调用自定义类加载器加载
(1)系统类加载器加载同一个类型时(即类的全限名一致),加载的Class实例只有一个,并且只加载一次。双亲委派模型
MyClassLoader myClassLoader1 = new MyClassLoader(); Class<?> clazz1 = myClassLoader1.loadClass(Sample.class.getName()); MyClassLoader myClassLoader2 = new MyClassLoader(); Class<?> clazz2 = myClassLoader2.loadClass(Sample.class.getName()); System.out.println(myClassLoader1==myClassLoader2);// false System.out.println(clazz1==clazz2);// true
Class<?> clazz1 = ClassLoader.getSystemClassLoader().loadClass(Sample.class.getName()); Class<?> clazz2 = ClassLoader.getSystemClassLoader().loadClass(Sample.class.getName()); System.out.println(clazz1.getClassLoader());// sun.misc.Launcher$AppClassLoader@2a139a55 System.out.println(clazz1==clazz2);// true
(2)用户自定义类加载器加载同一个类型时,可以加载多个Class实例。通过这种方式来破坏双亲委派模型,典型的应用如:Tomcat
MyClassLoader myClassLoader1 = new MyClassLoader(); Class<?> clazz1 = myClassLoader1.findClass(Sample.class.getName()); MyClassLoader myClassLoader2 = new MyClassLoader(); Class<?> clazz2 = myClassLoader2.findClass(Sample.class.getName()); System.out.println(myClassLoader1==myClassLoader2);// false System.out.println(clazz1==clazz2);// false
调用 findClass 表示这个类是通过自定义类加载器加载的
clazz1==clazz2 为false说明class实例在堆内存中属于不同的实例。
备注:因为上面 MyClassLoader中的findClass方法是protected类型,可能在其它包下无法访问!因此,需要再重写一个public类型的 loadClass 方法
标签:com jdk als package 码流 public input 双亲委派模型 not
原文地址:https://www.cnblogs.com/caoxb/p/12735536.html