一.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。
相关推荐
Java ClassLoader定制实例
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:688) at java.lang.ClassLoader.loadClass(ClassLoader.java:667) at com.ibm.ws.bootstrap.ExtClassLoader.loadClass(ExtClassLoader.java:119) at...
java classloader classpath 张孝祥
at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang....
破解java加密的ClassLoader.java,在classloader植入破解代码
主要内容包括 Java类加载机制及加载流程,以及如何定义自己的类加载器,如何实现类的热替换。
理解Java ClassLoader机制
Java ClassLoader Tutorial
classloader 源码,自定义classloader
Sun 官方关于 ClassLoader原理的文章,值得一看
Understanding the Java ClassLoader
Java中ClassLoader的解析,从ClassLoader的角度分析了JVM,装载类,创建类的对象的整个过程,更清晰的了解JVM的运行机制。
深入了解Java_ClassLoader,Bytecde.pdf
NULL 博文链接:https://sbiigu.iteye.com/blog/260456
Understanding the Java ClassLoader.pdf
java classloader 讲义-淘宝网
java classLoader 的全面讲解 从基本概念到具体的应用 里面共有三份资料。
Java 虚拟机中ClassLoader 相关简介 双亲委托机制 Android 中ClassLoader 简介
LazyWorker.zip,一个智能控制进入电子邮件地址,自动检查是否存在域,如果域可以接收电子邮件。LaZyWork是一个帮助类延迟任务。例如,检查需要网络操作且不应在每次按键关闭后进行的输入。