java main方法背后的故事?(转)

jvm java 看似一种语言,实则一个巨大的体系的王国,开发这么多年了,还是没有搞懂,我以为我懂了,可是过了一段时间又忘了,所以说还是没懂

1、main方法说起

编译完我们的java文件后,需要有个一含有main方法的类,java 命令将指示操作系统启动一个jvm进程

这个jvm进程启动后,寻找那个main地方开始执行程序

java [JVM_Options] ClassName_with_main [args_separate_space]

main方法的签名必须是 pubic static void main(String[] args) why?

简单点:

首先,main方法是JVM(java虚拟机)自动调用

JVM调用main方法的位置自然不会在某个类中、或某个包中,因此只有当main方法在公有级别上时,才对JVM可见,所以mian方法需要public修饰,

main方法所在的类也需要public修饰符。

由于main方法是所有程序的入口,也就是main被调用时没有任何对象创建,不通过对象调用某一方法,只有将该方法定义为静态方法,所以main方法是一个静态方法,既需要static修饰。

JVM对于java程序已经是最底层,由它调用的方法的返回值已经没有任何地方可去,因此,main方法返回值为空,既需用void修饰。

至于main方法的参数String[ ] arg我们现在已经很少有机会去用它了,它用于在接受命令行传入的参数

2、执行main方法之前发生了神马

可以参看 jvm源码分析

首先要明确 jvm进程 是操作系统的进程,该进程是多线程机制的

我们明确两种线程:

jvm线程:指jvm自行管理的线程,我们在程序中无法操控,多是守护类型的

java线程:指从java技术角度看 jvm、我们在程序中用Thread类或Runnable接口编写产生的线程,可操控的线程

至于 java线程 在 jvm里面是怎么实现的,怎么对应到os级别的线程的,请看  http://my.oschina.net/jingxing05/blog/275334

明确两类不同的线程之后,执行main方法之前: LoadJavaVM

jvm进程启动了多个jvm线程(很可能是错的,如有,请赐教):

jvm线程:

  • 启动 VM Thread, 单例的,所有线程之始祖!这个线程自轮询loop从对一个队列中取操作任务,来产生其他线程
  • 根据jvm抽象规范,可能有执行引擎线程,GC线程,classloader线程

在jvm自身启动和初始化之后,会

ContinueInNewThread(JavaMain, threadStackSize, (void*)&args);

即启动一个叫main的线程来执行  入口的main方法,main线程虽然不是我们手动生出的线程,但ta还是一个非守护线程

3、main执行过程

  • 加载类

执行main方法时,jvm进程发现main所在类没有在方法区,于是开始进行classload

类加载完的最后一步是 根据情况决定  是不是要进行类的初始化

在main执行之前,必须先对类进行初始化。初始化类的变量,还有静态代码块。初始化的时候还要先初始化它的父类。每个类都有一个隐含的父类Object。

初始化的顺序:类变量和静态块按序,先父后子

类的初始化过程发生时刻:

1. T是一个类,当T的一个实例创建的时候,也就是T t = new T();

2. T的一个静态方法被调用的时候,也就是 T.staticField();

3. T的静态属性被赋值的时候,T.staticField = o;

4. T的一个静态属性被使用的时候,也就是 Object o = T.staticField; 但是它不是常量。

5. T is a top level class , and an assert statement  lexically nested

within T  is executed. (不懂,求解)

  • 执行main方法

将方法需要的参数,局部变量,本地方法,操作数等以 栈帧的结构 push到 main线程的堆栈区,然后执行引擎线程开始执行,执行完毕,将该栈帧 pop掉。main线程的堆栈区没有栈帧时,main线程消退。

  • 卸载类对象

这一步是个优化的步骤,释放一些方法区的内存,jvm自己决定要不要这一步,一般不会去卸载方法区的

  • 程序退出

1. 所有的非daemon线程都终止了

2. 某个线程调用了类Runtime或者System的exit方法

main程序执行图

类加载详细过程

jvm中的一些线程可参看 http://ifeve.com/jvm-thread/

http://my.oschina.net/jingxing05/blog/282867?p={{currentPage+1}}

时间: 2024-12-11 11:26:26

java main方法背后的故事?(转)的相关文章

从java main方法说开去

刚刚接触java语言时,接触的便为一个java main方法.我们知道这样程序就可以运行了,但是程序是怎么运行起来的我们却不知道. 众所周知,当执行一个java程序时,首先会启动一个JVM虚拟机进程,当程序执行完时,JVM进程则消亡.其他导致JVM进程消亡的还有以下情况: System.exit(int)方法,执行该方法时,虚拟机腿粗好.int参数为状态码,为0时,正常退出:若不为0,则异常退出. 遇到异常或错误时.若在程序过程中遇到异常时,不作处理会一直抛出异常到main函数,若main函数也

07 java main方法

1.问题:Java main方法为什么是  public static void main(String[] args)??? 序号 场景 编译 运行 解释 1 public修改为private protected或者去掉 正常 Main Method not public 只有当main方法在公有级别上时才对JVM可见,所以需要使用public修饰 2 去掉static Exception in thread "main" java.lang.NoSuchMethodError:ma

从java main方法说开去(转)

刚刚接触java语言时,接触的便为一个java main方法.我们知道这样程序就可以运行了,但是程序是怎么运行起来的我们却不知道. 众所周知,当执行一个java程序时,首先会启动一个JVM虚拟机进程,当程序执行完时,JVM进程则消亡.其他导致JVM进程消亡的还有以下情况: System.exit(int)方法,执行该方法时,虚拟机腿粗好.int参数为状态码,为0时,正常退出:若不为0,则异常退出. 遇到异常或错误时.若在程序过程中遇到异常时,不作处理会一直抛出异常到main函数,若main函数也

为什么使用Junit Test而不用普通java main方法来完成测试?

因为在程序里边,一个接口对应一个实现方法,而在接口中常常会定义相关的很多方法,所以在测试的时候,如果都在main方法里边进行测试,main方法就会显得臃肿,而且不便于以后其他人测试以及查看测试数据,用Junit Test测试的话,一个方法对应一个测试方法,简单明了,也方便别人查看测试方法以及测试数据. 如果你的类里有多个方法,用main方法测试的话就很不方便,想测试全部方法的话就得把测试代码全部写到main里,或者你测一个重写一次.且更重要的是,这样会使测试代码与运行逻辑代码混在一起,不规范.

Java main方法继承

java中main方法是可以继承的 Test1.java package Variables; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("Test1.main()"); System.out.println(Thread.currentThread().getStackTrace()[1].get

Java main方法解释

java--main()方法 在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main,方法必须是public static void 类型的,方法必须接收一个字符串数组的参数等等. 在看Java中的main()方法之前,先看一个最简单的Java应用程序HelloWorld,我将通过这个例子说明Java类中main()方法的奥秘,程序的代码如下: /** * Jav

linux 调用java main方法

#!/bin/shexport LANG=zh_CNtimestamp=`date +%Y%m%d%H%M`/opt/java6/bin/java -Xms128m -Xmx512m -Dfile.encoding=gbk -classpath /weblogic/mpms_job/WEB-INF/classes:/weblogic/mpms_job/mpms_job.jar:/weblogic/mpms_job/lib/*  com.guohualife.mpms.app.StartMpmsT

使用Maven运行Java main的3种方式

使用Maven运行Java main的3种方式 原文  http://blog.csdn.net/qbg19881206/article/details/19850857 主题 Maven maven使用exec插件运行java main方法,以下是3种不同的操作方式. 一. 从命令行运行 1.运行前先编译代码,exec:java不会自动编译代码,你需要手动执行mvn compile来完成编译. mvn compile 2.编译完成后,执行exec运行main方法. 不需要传递参数: mvn e

using关键字背后的故事!

using关键字的作用: 1:可以引入命名空间2:可以释放资源 *****不能使用using语句完全替换掉(try-catch-finally)语句(无法进行异常处理) 在出了using语句的{}后,系统会自动释放资源(系统自动调用了Dispose()方法)而在Dispose方法中是这么实现的 3:哪些对象可以被using语句回收掉呢?必须实现了IDisposable接口的类型才可以被using语句引用! 4:IDisposable接口的Dispose()方法背后的故事! 接口中的Dispose