一.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
相关推荐
JavaLauncher源码分析——TNFLauncher:洞察启动器的核心机制 在Java应用程序的世界中,启动器(Launcher)起着至关重要的作用,它负责解析命令行参数,设置环境变量,加载类并执行主方法。TNFLauncher是这样一个...
JavaLauncher源码分析 在Java开发领域,启动器(Launcher)是程序运行的关键部分,它负责加载类、初始化环境以及执行应用程序。对于"Minecraft Launcher"这样的游戏启动器来说,其重要性更是不言而喻,因为它不仅要...
Java类加载器(ClassLoader)是Java虚拟机(JVM)的核心组成部分,负责将类的字节码转换为可运行的Java对象。Java类加载器分为三种主要类型:引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ...
上述代码展示了如何创建一个自定义类加载器`MyClassLoader`,该类继承自`java.lang.ClassLoader`。`MyClassLoader`的主要功能是从文件系统中加载指定类的二进制数据。 - **构造函数**:接受一个父类加载器和基础...
6. `launcher`:Java启动器,负责解析命令行参数、加载JVM、启动主类等,它是Java程序运行的第一步。 三、重点源码解析 1. 集合框架:Java 1.8引入了Stream API,使得集合操作更加简洁和高效,通过lambda表达式和...
通过阅读和分析JDK1.8的源码,开发者不仅可以深入了解Java语言的实现,还能学习到优秀的编程实践和设计模式,为日常开发工作提供强大支持。同时,对于优化代码性能、解决并发问题以及深入理解Java生态系统有着不可...
Java Development Kit (JDK) 源码是学习和理解Java平台核心机制的关键资源。它包含了许多关键组件的源代码,使开发者能够深入探索Java语言的底层实现,从而提升编程技巧,优化性能,并理解标准库的工作原理。在这个...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...
JDK1.6版本是Java历史上的一个重要里程碑,它的源码对于我们深入理解Java语言的工作原理以及学习Java虚拟机(JVM)的内部机制具有极大的价值。 1. **Java运行环境** JDK1.6的源码揭示了Java运行环境的实现,包括类...
2. **类加载机制**:`sun.misc.Launcher`和`java.lang.ClassLoader`展示了类如何被加载到JVM中。 3. **线程与并发**:`java.lang.Thread`和`java.util.concurrent`包提供了线程管理和并发控制的实现。 4. **反射...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...
《深入解析OpenJDK 1.6.0.41源码:聚焦类加载器与sun.misc.Launcher》 在Java开发过程中,对JVM内部机制的理解是提升技术水平的关键一步,尤其是类加载器(ClassLoader)和其核心实现sun.misc.Launcher。然而,随着...
总之,这个压缩包提供了一个深入研究JVM类加载机制的机会,无论是对`loadClass`方法的理解,还是通过`Launcher`源码分析JVM启动流程,都将增强我们对Java运行时环境的掌握。这些知识对于Java开发者,尤其是对性能...
例如,`java.lang.ClassLoader`的`loadClass()`方法,以及其子类如`sun.misc.Launcher$AppClassLoader`的实现,可以帮助我们理解双亲委派模型的实现细节。 通过以上内容,我们可以了解到Java类加载器在Java程序运行...
Java8源码学习 ├── com/ ├── java/(常用代码都在此文件夹下) │ ├── lang/ │ │ ├── ClassLoader │ │ ├── Enum │ │ ├── Integer │ │ ├── Long │ │ ├── String │ │ ├── ...