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

[Java] JVM 在执行 main 方法前的行为的更多相关文章

  1. 第2篇-JVM虚拟机这样来调用Java主类的main()方法

    在前一篇 第1篇-关于JVM运行时,开篇说的简单些 中介绍了call_static().call_virtual()等函数的作用,这些函数会调用JavaCalls::call()函数.我们看Java类 ...

  2. 第4篇-JVM终于开始调用Java主类的main()方法啦

    在前一篇 第3篇-CallStub新栈帧的创建 中我们介绍了generate_call_stub()函数的部分实现,完成了向CallStub栈帧中压入参数的操作,此时的状态如下图所示. 继续看gene ...

  3. Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  4. 【异常】idea执行Main方法出现 Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest

    一.异常复现步骤 1)首先得是一个Spring MVC项目 注:Spring Boot项目有内置的web 容器,不会出现该问题 2)main方法存在于使用HttpServletRequest类的类中 ...

  5. Java程序入口:main()方法讲解

    Java程序的入口---main()方法的签名为:public static void main(String[] args) {...} ,其中, ♦ public修饰符:Java类由JVM调用,为 ...

  6. 第29篇-调用Java主类的main()方法

    在第1篇中大概介绍过Java中主类方法main()的调用过程,这一篇介绍的详细一点,大概的调用过程如下图所示. 其中浅红色的函数由主线程执行,而另外的浅绿色部分由另外一个线程执行,这个线程最终也会负责 ...

  7. 反射中的一个问题点:利用Method执行main方法特殊的地方

    利用Method执行main方法 问题: 启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个m ...

  8. java语言规范,main方法必须声明为public

    注释: 根据java语言规范,main方法必须声明为public. 当main方法不是public时,有些版本的java解释器也可以执行java应用程序.有个程序员报告了这个bug. 如果感兴趣可以查 ...

  9. Ideal test 不执行main方法了

    参考:idea 导入项目后不能执行main方法 用了ideal之后,发现自己的项目里面没有test文件夹,自己建了一个,发现竟然不能执行main函数, 后来经过点播之后,才知道,光建立文件夹是没用的, ...

随机推荐

  1. 微信,QQ这类IM app怎么做——谈谈Websocket

    前言 关于我和WebSocket的缘:我从大二在计算机网络课上听老师讲过之后,第一次使用就到了毕业之后的第一份工作.直到最近换了工作,到了一家是含有IM社交聊天功能的app的时候,我觉得我现在可以谈谈 ...

  2. Shell 获取当前时间

    #! /bin/bash time=`date '+%Y-%m-%d %H:%M:%S'` # echo $time sql='SELECT `username`, `password` FROM ` ...

  3. vsftp配置主动模式和被动模式

    配置文件:/etc/vsftpd/vsftpd.conf 主动模式配置方法: 主动式连接使用的数据通道 connect_from_port_20=YES 支持数据流的被动式连接模式 pasv_enab ...

  4. Python之路,Day15 - Django适当进阶篇

    Python之路,Day15 - Django适当进阶篇   本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣 ...

  5. AsyncTask和Handler的对比

    AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操 ...

  6. MVC4使用EF6连接mysql数据库

    1.需要安装MySql.Data.Entity.EF6,此dll可以在项目——>管理NuGet程序包里联机搜索MySql.Data.Entity.EF6并安装即可 2.连接字符串需要添加prov ...

  7. JavaScript回调函数的理解

    这里是个人对回调函数的一段理解 <!DOCTYPE html> <html> <head> <title>回调函数</title> < ...

  8. html table 知识点

    第一点就是图片在表格中不能对齐边沿的问题,这是和浏览器的渲染模式相关的,在标准模式中是不能对齐的,除非改变CSS某些样式.而在准标准模式和怪异模式中,默认就是对齐的. 这一特性在以前的表格布局时代是大 ...

  9. SystemConfig.getPropertyValue("test");配置文件已经加了test=abc,但是取得时候空字符串

    1.定位tomcat中System.properties是否配置了,发现配置了 2.定位myeclipse中修改的tomcat是不是自己配置的tomcat.发现是 3.定位如下位置配置是否读取我先在用 ...

  10. iOS几种简单有效的数组排序方法

    第一种,利用数组的sortedArrayUsingComparator调用 NSComparator ,obj1和obj2指的数组中的对象 NSComparator cmptr = ^(id obj1 ...