`

java自带的classloader

    博客分类:
  • jvm
阅读更多

sun jre本身的classloader主要包含三个loader,分别是
1. Bootstrap class loader->C代码  (加载%java_home%/lib/*)
2. Extensions class loader->ExtClassLoader    (%java_home%/lib/ext/*)
3. System class loader->AppClassLoader        (加载classpath下的类)

 

为什么他们会加载这些路径下面的class呢?
ExtClassLoader和AppClassLoader的构造函数可以看出

 

        String s = System.getProperty("java.class.path");
        new ExtClassLoader(s, extcl);
       
        String s = System.getProperty("java.ext.dirs");
        new AppClassLoader(s, extcl);

 


ExtClassLoader和AppClassLoader都继承于URLClassLoader,构造函数传递的path将来会作为加载class的路径范围

(注: ExtClassLoader和AppClassLoader不属于标准的java api,是sun.misc.Launcher的内部类,具体源码在openjdk中,在线地址为
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/misc/Launcher.java


那如何加载字节码class文件呢?
以AppClassLoader为例,当需要它加载A.class时,会调用其loadClass(String name, boolean resolve)方法,
此方法会通过super.loadClass(name, resolve)交由父类,最终由java.lang.ClassLoader处理,代码如下
(java.lang.ClassLoader.loadClass方法)

    protected synchronized Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
    {
    // First, check if the class has already been loaded
    Class c = findLoadedClass(name);
    if (c == null) {
        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.
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
    }
 


从这段代码可以看出加载class有一个委托的模型,AppClassLoader,ExtClassLoader, Bootstrap classoader在建立初期就创建了一个所谓的父子关系(并不是继承关系),
如图
  
其后在加载具体class的时候会有个委托parent classloader加载,parent加载不到,再由自己加载的过程,目的就是为了安全,防止java的核心类库被修改,如果用这种模型,java.lang.String类就不能由用户自己去实现,
因为他肯定最终还是Bootstrap classoader类去加载了,因为string.class是在%java_home%/lib/*下的rt.jar中
(注:如果你一定要自己写一个java.lang.String覆盖jre自己的,你可以自己实现classloader,然后违反委托模型,这是可以做到的)


可以看到上面的java.lang.ClassLoader.loadClass方法会调用 findClass(name)去真正得到一个class对象,此方法有ClassLoader的子类,ExtClassLoader和AppClassLoader的父类URLClassLoader实现,
具体方法实现如下(去掉不影响理解的代码)
(java.lang.URLClassLoader.findClass方法)

    protected Class<?> findClass(final String name) {
            String path = name.replace('.', '/').concat(".class");
            //ucp变量就是当初构造AppClassLoader的时候传递的路径,这里使用到
            Resource res = ucp.getResource(path, false);
            return defineClass(name, res, true);
    }
 


   
上面会继续调用到defineClass方法
(java.lang.URLClassLoader.defineClass方法)

private Class defineClass(String name, Resource res, boolean verify)
        throws IOException {
    int i = name.lastIndexOf('.');
    URL url = res.getCodeSourceURL();
 
    // Now read the class bytes and define the class
    ByteBuffer bb = res.getByteBuffer();
        byte[] bytes = ((bb == null)? res.getBytes() : null);
        // NOTE: Must read certificates AFTER reading bytes above.
        CodeSigner[] signers = res.getCodeSigners();
        CodeSource cs = new CodeSource(url, signers);

        if (!verify) {
            // Need to use reflection since methods are private in super class
            Object[] args = {
                name, (bb == null? ByteBuffer.wrap(bytes) : bb), cs
            };
            try {
                return (Class) defineClassNoVerifyMethod.invoke(this, args);
            } catch (IllegalAccessException iae) {
                // Should never happen; fall back to the regular defineClass
            } 
        }
        return (bb != null? defineClass(name, bb, cs) :
                        defineClass(name, bytes, 0, bytes.length, cs));
    }
 

上面方法会先通过stream的方式读取字节码转为byte数组,然后最终交由ClassLoader的defineClass1方法
(java.lang.ClassLoader.defineClass1方法)

  private native Class defineClass1(String name, byte[] b, int off, int len,
                                  ProtectionDomain pd, String source,
                                      boolean verify);
 


上面方法是native方法,这是加载字节码的最后一步,可以想象,这必须由jvm本身来实现

以上总结:加载class首先有个委托的过程,而加载本身又是经历根据路径寻找字节码,加载字节流,讲字节流转为Class对象的过程

分享到:
评论

相关推荐

    java中classLoader的使用

    Java中的类加载器(ClassLoader)是Java虚拟机(JVM)的一个重要组成部分,它负责将类的.class文件从文件系统或者网络中加载到内存中,并转换为对应的Class对象。类加载器的工作流程主要包括加载、验证、准备、解析...

    Java_ClassLoader详解

    这表明 `ClassLoaderTree` 类由 `Launcher$AppClassLoader` 加载,其父类加载器为 `Launcher$ExtClassLoader`,最终父类加载器为 `Bootstrap ClassLoader`,由于后者是系统自带且无法通过 Java 程序访问,因此返回 `...

    破解java加密的rt.jar,在classloader植入破解代码

    破解java加密的rt.jar,在classloader植入破解代码,默认输出到c:/TEMP/classes/目录。使用方法:只要下载本rt.jar,然后替换掉jdk1.8.0_25\jre\lib目录下的rt.jar。然后运行你需要破解的java程序即可,如果你的java...

    j-classloader-ltr

    - **Bootstrap ClassLoader**:这是JVM自带的类加载器,用于加载JVM的核心类库,如`java.lang`包下的类。 - **Extension ClassLoader**:由`sun.misc.Launcher$ExtClassLoader`实现,负责加载`JAVA_HOME/lib/ext`...

    探索JVM底层奥秘ClassLoader源码分析与案例讲解

    Bootstrap ClassLoader主要负责加载JDK自带的类库,如rt.jar;Extension ClassLoader则加载Java的扩展类库,如jre/lib/ext目录下的jar文件;AppClassLoder加载用户自定义的类,即classpath路径下的类。 在源码层面...

    Java-FootballGame.rar_java 足球_java足球小游戏

    - **内存管理**:Java 自带垃圾回收机制,但开发者仍需关注对象创建和销毁,避免内存泄漏。 6. **调试与测试** - **Junit**:Java 测试框架 JUnit 可用于编写单元测试,确保代码的正确性。 - **集成开发环境...

    ClassLoader in OSGI

    ### Java中的ClassLoader技术及其在OSGI模块隔离中的运用 #### 一、基本概念 Java引入了虚拟机的概念,即Java虚拟机(JVM),它在硬件平台和编译程序之间添加了一层抽象层,使Java程序能够跨平台运行。Java程序...

    Tomcat 5.0.18 ClassLoader source code insight

    1. Bootstrap ClassLoader:这是JVM自带的,加载Java核心库(如rt.jar)。 2. Common ClassLoader:加载`CATALINA_HOME/lib`目录下的所有JAR文件。 3. Shared ClassLoader:用于加载多个Web应用共享的类库,存在于`...

    Tomcat研究之ClassLoader.pdf

    1. **Bootstrap ClassLoader**:这是JVM自带的类加载器,负责加载JVM自带的核心类库以及`$JAVA_HOME/jre/lib/ext/*.jar`目录下的扩展类库。 2. **System ClassLoader**:通常由JVM的`java.class.path`系统属性指向...

    java class reload

    1. **Java ClassLoader原理** - Java程序在运行时,类的加载是由ClassLoader负责的。默认情况下,当类被加载后,除非应用停止,否则ClassLoader不会重新加载该类。 - Java的双亲委托模型(Parent Delegation Model...

    Java编程语言的基本原理.docx

    在编译阶段,程序员需要使用 JDK 中自带的 javac.exe 命令进行 Java 程序的编译。javac.exe 是一个 Java 编译器工具/命令,可以将 Java 源文件编译生成多个.class 文件。例如, javac Java 源文件的路径。 (二)...

    java的运行机制

    - **Bootstrap ClassLoader**:这是JVM自带的一个特殊类加载器,用于加载核心类库(如`rt.jar`)中的类。 - **Extension ClassLoader**:该加载器用于加载扩展类库中的类,这些类库位于`$JAVA_HOME/lib/ext`目录下。...

    JAVA 基础培训,JDK和JVM,核心类的介绍和使用

    虽然JVM自带的ClassLoader功能强大,但在特定情况下,自定义ClassLoader有其必要性: 1. **安全性增强**:在执行不可信代码前,可以使用自定义ClassLoader进行数字签名验证,增加系统的安全性。 2. **定制化构建**...

    java基础1

    Java SE是Java开发工具包(JDK)自带的标准API,涵盖了广泛的领域,包括面向对象编程、集合框架、网络编程、多线程、I/O流等。没有扎实的Java SE基础,就无法有效地进行Java EE或Java ME的开发。 Java类加载机制是...

    java-虚拟机 操作系统监控工具-源码

    支持Java代码热更新(可指定ClassLoader) 支持远程执行GC 支持远程执行JDK自带工具命令,包含但不限于jps、jstat、jstack、jinfo、jmap、jcmd等 提供客户端交互工具,支持跨进程attach和远程连接功能 支持三种服务...

    java杂谈——一个计算机专业学生几年的编程经验汇总谈

    在Java中,类加载由类加载器(Class Loader)完成,而类加载器分为三个层次:Bootstrap ClassLoader、Extension ClassLoader 和 Application ClassLoader。 1. **Bootstrap ClassLoader**:负责加载位于`&lt;JAVA_HOME&gt;\...

    Java反序列化回显解决方案.docx

    - **Bootstrap ClassLoader**:这是 JVM 自带的类加载器,负责加载核心类库(如 java.lang.*)。 - **Platform ClassLoader**:用于加载平台特定的扩展库。 - **App ClassLoader**:即系统的类加载器,负责加载...

    Tomcat加载顺序

    这是JVM自带的类加载器,用于加载核心的类库,如`java.lang`、`java.util`等,这些类库存储在`$JAVA_HOME/jre/lib`目录下。Bootstrap ClassLoader不会从磁盘上加载任何类,而是直接读取JRE中的这些核心类库。 #### ...

Global site tag (gtag.js) - Google Analytics