zoukankan      html  css  js  c++  java
  • [Java] JVM 在执行 main 方法前的行为

    JVM 执行一个 Java 程序时,先从某个指定的 Java 类的 main 方法开始执行代码,同时,传一个字符串数组作为 main 方法的参数。例如在 Unix 系统上,执行下面的命令

    java Test reboot Bob Dot Endzo

    JVM 会调用 Test 的 main 方法,同时把四个字符串 "reboot", "Bob", "Dot" "Endzo" 作为参数传给 main 方法。

    那么,在执行 main 方法前,JVM 需要做什么事情呢?本文将简单地回答这个问题。

    JVM 启动调用 main 方法,一共经过四个阶段:加载( Load )、链接( Linkage )、初始化( Initialization )、调用( Invocation )

    加载一个类 Test

      在最开始,JVM 里面是没有 Test 类的,准确地说,是没有 Test 类的二进制表代码,需要先加载 Test 。JVM 使用类加载器( class loader ) 去搜索 Test 的二进制代码,然后加载。如果类加载器搜索不到,则抛出异常。

    链接一个类 Test

      在 JVM 里面包含了 Test 类的二进制代码后,需要通过链接动作,将 Test 的二进制形式连接到 JVM 的运行时状态,然后才可以执行 Test 二进制代码。链接包含三个动作:验证( Verify ),准备( Prepare ),解析(Resolve),其中解析行为是可选的。

      验证:检查加载完的 Test 类二进制代码格式是否正确,语义是否符合 Java 语言规范、JVM 规范。

      准备:分配静态存储空间,以及任何 JVM 所需要的数据结构,例如方法列表( method table )

      解析:检查 Test 类引用的类或接口,加载所引用的其他类或接口,并检查他们是否正确。

    初始化一个类 Test

      初始化包括静态变量的初始化,和静态代码块的初始化。初始化是按文本顺序进行。如果 Test 类可以被初始化,其直接父类需要先被初始化了,而如果直接父类可以被初始化,直接父类的直接父类需要先被初始化了,以此递推。Object 类没有父类,所以 Object 类初始化后,递推结束。

      在初始化直接父类的时候,如果直接父类还没有被加载,则需要先加载、链接、初始化直接父类。所以,在初始化一个类阶段,有可能会抛出加载错误、链接错误、初始化错误。

    调用 Test.main 

      当前面的加载、链接、初始化都正常结束后,JVM 会调用 Test 的 main 方法。被调用的 main 必须被修饰为 public , static, void 。可接受的形式有两种:

      public staitc void mian(String[] args)

      public staitc void main(String... args)

      

    参考资料

    12.1 Java Virtual Machine Startup, The Java Language Specification, Java SE 8 Edition

  • 相关阅读:
    prometheus — nginx-vts-exporter
    jenkins的sbt插件安装
    centos 踩坑集锦
    Prometheus — Process-exporter进程监控
    Prometheus 自定义exporter 监控key
    prometheus — 基于文件的服务发现
    Prometheus 企业微信报警/inhibit抑制 /静默(二)
    centos7-- sbt的安装使用
    prometheus + grafana + node_exporter + alertmanager 的安装部署与邮件报警 (一)
    nginx配置
  • 原文地址:https://www.cnblogs.com/TonyYPZhang/p/5596637.html
Copyright © 2011-2022 走看看