一.Launcher
我们习以为常的ClassLoader.getSystemClassLoader()来获得系统类加载器,有没有考虑过到底是怎么得到的呢?阅读完Launcher的源码,就清楚了。
二.源码
public class Launcher { private static URLStreamHandlerFactory factory = new Factory(); private static Launcher launcher = new Launcher(); public static Launcher getLauncher() { return launcher; } private ClassLoader loader; //ClassLoader.getSystemClassLoader会调用此方法 public ClassLoader getClassLoader() { return loader; } public Launcher() { // 1. 创建ExtClassLoader ClassLoader extcl; try { extcl = ExtClassLoader.getExtClassLoader(); } catch (IOException e) { throw new InternalError( "Could not create extension class loader"); } // 2. 用ExtClassLoader作为parent去创建AppClassLoader try { loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( "Could not create application class loader"); } // 3. 设置AppClassLoader为ContextClassLoader Thread.currentThread().setContextClassLoader(loader); //... } static class ExtClassLoader extends URLClassLoader { private File[] dirs; public static ExtClassLoader getExtClassLoader() throws IOException { final File[] dirs = getExtDirs(); return new ExtClassLoader(dirs); } public ExtClassLoader(File[] dirs) throws IOException { super(getExtURLs(dirs), null, factory); this.dirs = dirs; } private static File[] getExtDirs() { String s = System.getProperty("java.ext.dirs"); File[] dirs; //... return dirs; } } /** * The class loader used for loading from java.class.path. * runs in a restricted security context. */ static class AppClassLoader extends URLClassLoader { public static ClassLoader getAppClassLoader(final ClassLoader extcl) throws IOException { final String s = System.getProperty("java.class.path"); final File[] path = (s == null) ? new File[0] : getClassPath(s); URL[] urls = (s == null) ? new URL[0] : pathToURLs(path); return new AppClassLoader(urls, extcl); } AppClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent, factory); } /** * Override loadClass so we can checkPackageAccess. * 这个方法似乎没什么必要,因为super.loadClass(name, resolve)时也会checkPackageAccess */ public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { int i = name.lastIndexOf('.'); if (i != -1) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { // sm.checkPackageAccess(name.substring(0, i)); } } return (super.loadClass(name, resolve)); } } }
三.源码说明
- Launcher源码里定义了static的扩展类加载器ExtClassLoader, static的系统类加载器AppClassLoader。
- 它们都是默认包级别的,它们都是继承URLClassLoader,这就意味着我们的代码里,不能定义ExtClassLoader laoder = ...或AppClassLoader loader = ...。我们只能ClassLoader loader = ...,而在实际运行时,我们应当能辨别这个loader到底是哪个具体类型。
- 在ExtClassLoader构造器里,并没有指定parent,或者说ExtClassLoader的parent为null。因为ExtClassLoader的parent是BootstrapLoader,而BootstrapLoader不存在于Java Api里,只存在于JVM里,我们是看不到的,所以请正确理解"ExtClassLoader的parent为null"的含义。
- 在AppClassLoader构造器里,有了parent。实例化AppClassLoader的时候,传入的parent就是一个ExtClassLoader实例。
- 看看Launcher的构造方法。
- 先实例化ExtClassLoader,从java.ext.dirs系统变量里获得URL[]。
- 用这个ExtClassLoader作为parent去实例化AppClassLoader,从java.class.path系统变量里获得URL[]。Launcher getClassLoader()就是返回的这个AppClassLoader。
- 设置AppClassLoader为ContextClassLoader。
四.例子
package com.jyz.study.jdk.classLoader; import java.net.URL; import sun.misc.Launcher; /** * 演示 * appClassLoader * extClassloader * bootstrapLoader * 所加载的文件 * @author JoyoungZhang@gmail.com * */ public class ClassLoaderTest { public static void main(String[] args) throws Exception { ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); ClassLoader extClassloader = appClassLoader.getParent(); ClassLoader bootstrapLoader = extClassloader.getParent(); System.out.println("the bootstrapLoader : " + bootstrapLoader); System.out.println("the extClassloader : " + extClassloader); System.out.println("the appClassLoader : " + appClassLoader); System.out.println(); System.out.println("bootstrapLoader加载以下文件:"); URL[] urls = Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.length; i++) { System.out.println(urls[i]); } System.out.println(); System.out.println("extClassloader加载以下文件:"); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(); System.out.println("appClassLoader加载以下文件:"); System.out.println(System.getProperty("java.class.path")); } } console output: the bootstrapLoader : null the extClassloader : sun.misc.Launcher$ExtClassLoader@1c78e57 the appClassLoader : sun.misc.Launcher$AppClassLoader@6b97fd bootstrapLoader加载以下文件: file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/resources.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/rt.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/sunrsasign.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/jsse.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/jce.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/charsets.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/modules/jdk.boot.jar file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/classes extClassloader加载以下文件: C:\Program Files\Java\jdk1.6.0_27\jre\lib\ext;C:\Windows\Sun\Java\lib\ext appClassLoader加载以下文件: E:\GoogleCode\platform-components\trunk\SourceCode\study-jdk\target\classes;E:\GoogleCode\platform-components\trunk\SourceCode\component-core\target\classes;C:\Users\audaque\.m2\repository\junit\junit\3.8.1\junit-3.8.1.jar
相关推荐
Java ClassLoader定制实例
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 38 ...
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 张孝祥
破解java加密的ClassLoader.java,在classloader植入破解代码
主要内容包括 Java类加载机制及加载流程,以及如何定义自己的类加载器,如何实现类的热替换。
理解Java ClassLoader机制
classloader 源码,自定义classloader
Sun 官方关于 ClassLoader原理的文章,值得一看
Java ClassLoader Tutorial
Java中ClassLoader的解析,从ClassLoader的角度分析了JVM,装载类,创建类的对象的整个过程,更清晰的了解JVM的运行机制。
Understanding the Java ClassLoader
深入了解Java_ClassLoader,Bytecde.pdf
NULL 博文链接:https://sbiigu.iteye.com/blog/260456
Understanding the Java ClassLoader.pdf
at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) ...9 more
java classloader 讲义-淘宝网
java classLoader 的全面讲解 从基本概念到具体的应用 里面共有三份资料。
Java 虚拟机中ClassLoader 相关简介 双亲委托机制 Android 中ClassLoader 简介