Java ClassLoader学习2:ClassLader源码
Java ClassLoader学习二:ClassLader源码
一.ClassLoader源码继承图
SecureClassLoader:这个类我没做深入研究,你把它当成一个增强版的ClassLoader,增强了从何地load class,增强了能不能load这些代码权限。
二.源码
public abstract class ClassLoader { // 父ClassLoader private ClassLoader parent; // 被此classLoader加载过的Class对象 private Vector classes = new Vector(); // The packages defined in this class loader. Each package name is mapped // to its corresponding Package object. private HashMap packages = new HashMap(); // 由虚拟机调用 void addClass(Class c) { classes.addElement(c); } // The packages defined in this class loader. Each package name is mapped // to its corresponding Package object. private final HashMap<String, Package> packages = new HashMap<String, Package>(); // 指明parent protected ClassLoader(ClassLoader parent) { this(checkCreateClassLoader(), parent); } // 不指名parent时使用SystemClassLoader protected ClassLoader() { this(checkCreateClassLoader(), getSystemClassLoader()); } // 默认resolve=false public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // 1 检查此class是否被此classloader加载过, // 最终是有native方法返回,native方法会使用到classes集合 Class c = findLoadedClass(name); // 1.1 未被加载 if (c == null) { try { // 1.1.1 此classloader有parent,委托parent去load if (parent != null) { c = parent.loadClass(name, false); } else {// 1.1.2 此classloader无parent = 启动类装载器去加载 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { } // 如果没有找到class,自己去加载试试 if (c == null) { c = findClass(name); } } // 找到的Class对象是否需要连接操作 if (resolve) { resolveClass(c); } // 1.2 被加载过,直接返回 return c; } protected final Class<?> findLoadedClass(String name) { if (!checkName(name)) return null; return findLoadedClass0(name); } // 如果name里包含/,或者虚拟机不支持class数组你使用了数组的时候返回false,其它情况返回true,包括空的name // eg com.jyz.component.core.collection.Tuple return true private boolean checkName(String name) { if ((name == null) || (name.length() == 0)) return true; if ((name.indexOf('/') != -1) || (!VM.allowArraySyntax() && (name.charAt(0) == '['))) return false; return true; } // 检查package是否可访问 private void checkPackageAccess(Class cls, ProtectionDomain pd) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { // ... } domains.add(pd); } // 自定义classloader时重写此方法 protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); } // 将byte数组转换成一个Class对象,最终有native方法实现 // 同一个byte数组,被不同的classloader加载,产生两个不同的Class对象 protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError { return defineClass(name, b, off, len, null); } /* * Determine protection domain, and check that: - not define java.* class, - * signer of this class matches signers for the rest of the classes in * package. */ //native的defineClass时会调用此方法检查name是否合法 //首先checkName,然后还需要!name.startsWith("java.") //所以我们定义了java.mypackage包,都将异常 //java.lang.SecurityException: Prohibited package name: java.mypackage private ProtectionDomain preDefineClass(String name, ProtectionDomain protectionDomain) { if (!checkName(name)) throw new NoClassDefFoundError("IllegalName: " + name); if ((name != null) && name.startsWith("java.")) { throw new SecurityException("Prohibited package name: " + name.substring(0, name.lastIndexOf('.'))); } //... } // protected的resolveClass方法,可以在自定义的classloader调用 protected final void resolveClass(Class<?> c) { resolveClass0(c); } //获得appClassLoader,实际调用Launcher完成 public static ClassLoader getSystemClassLoader() { sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); return l.getClassLoader(); } }
三.源码说明
- loadClass这个类是重点。
- 检查此class是否被此classloader加载过,有直接返回此class
- 检查此ClassLoader有无parent,有委托parent去load。无说明此CassLoader为ExtClassLoader,交给BootstrapLoader去加载。其实可以说委托parent去加载
- 某个ClassLoaer的parent并未加载到指定class,自己findClass(String name)去加载。
- 最后判断找到的Class对象是否需要连接操作并执行。
- 自定义classloader时重写findClass(String name)。
- ClassLoader.etSystemClassLoader()实际由sun.misc.Launcher去完成。
- ClassLoader构造函数里,不指名parent的话使用AppClassLoader。