1 类加载的责任链模式
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
执行过程jdk7
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
使用双亲委派的方式目的是为了安全性和避免重复,例如可以防止用户自定义的java.lang.String类覆盖jdk内置的String类,对系统造成破坏。
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html
2 类加载器体系结构
Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。是类加载器树的根节点。
Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
System ClassLoader(AppClassLoader)/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。
以上3个都是jvm的内建实现。
User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。
http://blog.chenlb.com/2009/06/java-classloader-architecture.html
http://boy00fly.iteye.com/blog/1096912
默认情况下,jvm会启动Bootstrap\Extension 类加载器加载jdk的核心类,然后app类加载器再去加载classpath(包括操作系统环境变量中)中的类。
除了文件系统,class还有可能来自网络的。可以通过java.lang.ClassLoader.defineClass(String name, byte[] b, int off, int len)方式定义,再由Class.newInstance()实例化。
3 自定义类加载器
用于支持动态类加载,也是java安全的一种手段。不同的类加载器产生不同的命名空间,不同命名空间中的类默认不可相互访问。防止不可信任的代码恶意修改、破坏另一个类加载器中的正常代码。