java程序启动时会发生什么?

java程序启动时会发生什么?,java,jar,jvm,classloader,executable-jar,Java,Jar,Jvm,Classloader,Executable Jar,最近有人接触了Java类加载器,并突然意识到当有人调用时,一步一步地发生了什么 java -jar App.jar 嗯,我想 创建了一个新的JVM实例 它使用类加载器加载主类和其他类 字节码从main()方法开始执行 但我仍然认为有很多事情我需要了解更多 谁和如何决定启动时应该加载哪些类以及需要加载哪些类 我发现了两个相关的问题,但没有解释如何将其应用到Java现实中 •谁和如何决定启动时应加载哪些类以及需要加载哪些类 我们需要了解java类加载的基本原理。最初,引导类加载器(作为VM

最近有人接触了Java类加载器,并突然意识到当有人调用时,一步一步地发生了什么

java -jar App.jar
嗯,我想

  • 创建了一个新的JVM实例
  • 它使用类加载器加载主类和其他类
  • 字节码从main()方法开始执行
  • 但我仍然认为有很多事情我需要了解更多

    • 谁和如何决定启动时应该加载哪些类以及需要加载哪些类
    我发现了两个相关的问题,但没有解释如何将其应用到Java现实中

    •谁和如何决定启动时应加载哪些类以及需要加载哪些类

    我们需要了解java类加载的基本原理。最初,引导类加载器(作为VM本身的一部分在本地实现)负责加载核心系统类。还有其他类加载器,如扩展、系统、用户定义(可选)类加载器,它们决定何时以及如何加载类。
    这个决定是由类加载器做出的。有不同的实现,其中一些预加载所有可以加载的类,另一些只加载需要的类

    一个类只有在第一次从程序代码访问时才需要加载;这种访问可以是该类中对象的实例化,也可以是对其
    静态成员之一的访问。通常,默认类加载器会在需要类时延迟加载它们

    但是,在任何情况下都不能依赖于预加载某些类:在实际执行此代码之前,可能无法确定通过
    Class.forName(…)
    访问的类

    在其他选项中,对于简单的实验,您可以使用静态初始化器代码查看实际加载类的时间和顺序;该代码将在类第一次加载时执行;例如:

    class SomeClass {
    
        static {
            System.out.println("Class SomeClass was initialized.");
        }
    
        public SomeClass() {
            ...
        }
    
        ...
    
    }
    
    您的示例显示了一个可执行jar,它只是一个普通的java存档(jar),在它的清单文件中有一个额外的键/值对(位于文件夹
    “META\u INF”
    )。键是“
    Main Class
    ”,如果您像示例中那样“运行”jar,则该值是将执行其“Main”方法的类的完全限定类名


    jar是一个zip文件,您可以查看每个zip存档工具的内部信息。

    每当您编译Java程序时,都会执行以下步骤

  • 首先,类装入器将类装入JVM
  • 在给出命令javac filename.java后,编译器检查编译时错误,如果一切正常,它将生成.Class文件(字节码)
  • 这将是第一阶段

    稍后,解释器检查运行时错误,如果一切正常,没有异常,则解释器将字节码转换为可执行代码


    java的第一个阶段是由JIT编译器(准时制)完成的。

    该规范可能会有所帮助(有点迟钝,因此是一个注释而不是答案):该链接还涉及java VM规范: