一个简单程序的类加载流程

 手机用户2502903213 发布于 2023-02-07 21:04

我刚刚开始学习Java的内部架构.我已经粗略地理解了类加载的概念,它在jvm运行时加载所需的类,ClassNotFoundException在没有找到类时抛出,特定的类加载器加载类引用的类.

有人可以清楚地解释类加载的流程,即下面的示例Java代码中的引导类加载和用户定义的类加载的顺序.

import java.io.File;
public class Sample
{
    public static void main(String[] args)
    {
        String fileName = "sample";
        File file = new File(fileName);
        file.isFile();
    }
} 

我还从一个参考资料中学到了" classloader维护它加载的类的名称空间".通过名称空间,这是否意味着类的文字名称?也有人可以解释一下这个含义/优点吗?

4 个回答
  • 您将按Sample如下方式运行您的课程

    > java Sample

    对于小魔术,检查-verbose:class选项的输出,你会看到大量的以下行..

    [Opened C:\jdk1.6.0_14\jre\lib\rt.jar]
    [Loaded java.lang.Object from C:\jdk1.6.0_14\jre\lib\rt.jar]
    [Loaded java.io.Serializable from C:\jdk1.6.0_14\jre\lib\rt.jar]
    [Loaded java.lang.Comparable from C:\jdk1.6.0_14\jre\lib\rt.jar]
    .
    .
    .
    .
    .
    .
    [Loaded java.security.cert.Certificate from C:\jdk1.6.0_14\jre\lib\rt.jar]
    [Loaded Sample from file:/D:/tmp/]
    [Loaded java.lang.Shutdown from C:\jdk1.6.0_14\jre\lib\rt.jar]
    [Loaded java.lang.Shutdown$Lock from C:\jdk1.6.0_14\jre\lib\rt.jar]
    

    \jre\lib\rt.jar在类加载Bootstrap器(或Primordial)加载类之前,您会看到一堆类被加载.这些是运行任何由Bootstrap加载的Java程序的先决条件.

    另一组jar由Extension类加载器加载.在这个特定的例子中,不需要lib中的任何类,\jre\lib\ext因此它没有被加载.但Extension类加载器专门分配了从扩展lib加载类的任务.

    编辑:除了标准平台java类之外,Sun/Oracle还提供了一组用于扩展平台核心API的jar .放置在扩展lib文件夹中的jar自动放在类路径中,因此不需要显式地包含在类路径中.这是关于同一主题的好官方文章.

    最后,在Bootstrap和Extension完成加载后,您的类SampleApplication类加载器加载.

    2023-02-07 21:07 回答
  • 类加载器层次结构

    每当启动新的JVM时,引导类加载器都负责将关键Java类(从java.lang包)和其他运行时类首先加载到内存中.引导类加载器是所有其他类加载器的父级.因此,它是唯一没有父母的人.

    接下来是扩展类加载器.它有bootstrap类加载器作为父类,负责从.jar保存在java.ext.dirs路径中的所有文件加载类- 无论JVM的类路径如何,它们都可用.

    开发人员的角度来看,第三个也是最重要的类加载器是系统类路径类加载器,它是扩展类加载器的直接子代.它从CLASSPATH环境变量,java.class.path系统属性或-classpath命令行选项指定的目录和jar文件中加载类.

    类加载器层次结构

    ClassLoader命名空间

    在Java中,使用唯一标识的类, ClassLoader + Class因为同一个类可以由两个不同的类加载器加载.

    Class A loaded by ClassLoader A != Class A loaded by ClassLoader B
    

    它有什么用?

    为不同的类加载器定义不同的保护和访问策略很有帮助.举一个使用不同类加载器加载的applet的例子,你不希望第三方应用程序访问你的资源.因此,对于安全性,维护不同名称空间非常重要.

    2023-02-07 21:10 回答
  • JVM在加载类的permgen区域中维护一个运行时池.每当引用类时,默认类加载器都会在类路径中找到该类并将其加载到此池中.这不是特定于JDK中提供的用户定义的类或类.引用类时,它将加载到内存中.

    由ClassLoader加载的类内部存储在ClassLoader实例中

    // The classes loaded by this class loader. The only purpose of this table
    // is to keep the classes from being GC'ed until the loader is GC'ed.
    private final Vector<Class<?>> classes = new Vector<>();
    

    当需要将类添加到内存后,调用以下函数:

    // Invoked by the VM to record every loaded class with this loader.
    void addClass(Class c) {
        classes.addElement(c);
    }
    

    找到了有关类加载器如何工作的有用图表.

    在此输入图像描述

    2023-02-07 21:10 回答
  • Java虚拟机通过创建一个初始类,这是在一种实现依赖性方式的规定,使用引导类加载器(启动§5.3.1).然后,Java虚拟机链接初始类,初始化它和在其中声明的静态实例变量,最后调用公共类方法void main(String []).调用此方法会驱动所有进一步的执行.构成主方法的Java虚拟机指令的执行可以导致附加类和接口的链接(并因此创建),以及其他方法的调用.

    阅读此链接

    2023-02-07 21:13 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有