[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
[Java] JVM 在执行 main 方法前的行为的更多相关文章
- 第2篇-JVM虚拟机这样来调用Java主类的main()方法
在前一篇 第1篇-关于JVM运行时,开篇说的简单些 中介绍了call_static().call_virtual()等函数的作用,这些函数会调用JavaCalls::call()函数.我们看Java类 ...
- 第4篇-JVM终于开始调用Java主类的main()方法啦
在前一篇 第3篇-CallStub新栈帧的创建 中我们介绍了generate_call_stub()函数的部分实现,完成了向CallStub栈帧中压入参数的操作,此时的状态如下图所示. 继续看gene ...
- Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。
Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...
- 【异常】idea执行Main方法出现 Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
一.异常复现步骤 1)首先得是一个Spring MVC项目 注:Spring Boot项目有内置的web 容器,不会出现该问题 2)main方法存在于使用HttpServletRequest类的类中 ...
- Java程序入口:main()方法讲解
Java程序的入口---main()方法的签名为:public static void main(String[] args) {...} ,其中, ♦ public修饰符:Java类由JVM调用,为 ...
- 第29篇-调用Java主类的main()方法
在第1篇中大概介绍过Java中主类方法main()的调用过程,这一篇介绍的详细一点,大概的调用过程如下图所示. 其中浅红色的函数由主线程执行,而另外的浅绿色部分由另外一个线程执行,这个线程最终也会负责 ...
- 反射中的一个问题点:利用Method执行main方法特殊的地方
利用Method执行main方法 问题: 启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个m ...
- java语言规范,main方法必须声明为public
注释: 根据java语言规范,main方法必须声明为public. 当main方法不是public时,有些版本的java解释器也可以执行java应用程序.有个程序员报告了这个bug. 如果感兴趣可以查 ...
- Ideal test 不执行main方法了
参考:idea 导入项目后不能执行main方法 用了ideal之后,发现自己的项目里面没有test文件夹,自己建了一个,发现竟然不能执行main函数, 后来经过点播之后,才知道,光建立文件夹是没用的, ...
随机推荐
- CentOS7搭建SAMBA服务器实现与WIN10匿名共享文件
1.安装SAMBA yum -y install samba samba-client samba-common 2.修改文件打开数 vi /etc/security/limits.conf 最后添加 ...
- java中的数据库事务处理
/*java使用事务处理,首先要求数据库支持事务,如使用MYSQL的事务功能,就要求mysql的表类型为Innodb,*/ /*InnoDB,是MySQL的数据库引擎之一 与传统的ISAM与MyISA ...
- LinqJoin方法
Linq知识点总结: (一).构建两个List泛型集合 List<Person> list=new List<Person>() { ...
- Oracle处理特殊字符
检查数据库级的参数设置 select * from nls_database_parameters;
- 从cellForRowAtIndexPath 看cell的重用机制
今天突然发现一个问题,由于对UITableViewCell 的重用机制不是很了解,让我纠结很久: 用过reloadData时候,会调用cellForRowAtIndexPath方法,但是请看以下2种c ...
- Objective-C学习篇06—NSString与NSMutableString
NSString OC提供了定义字符串对象的方法,也就是将想要表达的字符串用一对双引号引起来,并在开头加上@.@是OC中的指令符,它告诉编译器@以后的内容为OC中的语法.比如@”Harbingwang ...
- 二、C# 数据类型
C#语言的基本类型包括8种整数类型.2种用于科学计算的二进制浮点类型.1种用于金融计算的十 进制浮点类型.1种布尔类型以及1种字符类型. 2.1 基本数值类型 C#中的基本数据类型都有关键字和它们关联 ...
- spring resttemplate中的转码
/* * 初始化RestTemplate,RestTemplate会默认添加HttpMessageConverter * 添加的StringHttpMessageConverter非UTF-8 所以先 ...
- sql注释
一般使用数据库客户端软件是navicat,上面写sql用的注释符号一般是“#”或者“/* */”,比如: #我是注释 /*我是注释*/ 记得之前看别人sql里用“--”作为注释符号,结果我今天也试了一 ...
- Objective-C内存管理与原理
尽管苹果在 iOS 5/ Mac OS X 10.7 开始导入ARC,利用 Xcode4.2 可以使用该机能.ARC就是自动引用计数,是一项为Objective - C程序在编译时提供自动内存管理的功 ...