如何运行java程序运行的过程 详细解析java程序运行的过程的运行方式?

我们都知道 Java 程序是运行在 JVM 中的。但你可能不知道一个 Java 程序在 JVM 中是怎样执行的。今天,就和大家来一探究竟。首先,来看一下 JVM 的运行时数据区域划分:程序计数器:字节码执行指示器,实时记录字节码执行的行号,线程私有。虚拟机栈:也是线程私有的,它主要用来为方法提供服务。一个方法被执行的时候,会创建一个栈帧,用来存放局部变量表、方法出口等信息。方法被调用时栈帧入栈,执行结束时栈帧出栈。本地方法栈:与虚拟机栈类似,只不过它的服务对象是本地(Native)方法。堆:堆可谓是与程序员打交道最多的一块区域了,也是 JVM 中最大的一块内存区域了。它里面主要用来存放的就是对象,垃圾回收主要就是针对这个区域。对于程序员来说,堆和栈(虚拟机栈)是与我们关系最紧密的部分。面向对象的核心成员就是对象和对象的行为(也就是方法),而堆和栈刚好是管着两块儿的。让我们回到标题中提出的问题:Java 程序在 JVM 中是怎样执行的呢?先看一段很简单的代码:public class Example {
public static void main(String[] args) {
a();
}
public static void a() {
int a = 1;
b();
}
public static void b() {
User b = new User();
}
}
代码很简单,一个类,main() 方法调用 a() 方法,a() 方法中定义了一个 int 变量 a,然后调用 b() 方法,b() 方法中 new 了一个 User 对象 b。
想要弄明白这个问题,你需要一丢丢的前置知识:栈中的局部变量表用于存放 Java 的基本类型和引用类型实例对象存放在堆内,栈中有对应的引用类型指向该实例的内存地址OK,下面用一个动画来展示一下上面那段代码是如何在 JVM 中运行的:Java 程序在 JVM 中是怎样执行的?可以结合下面的文字说明一起来看:程序运行main() 方法入栈a() 方法被调用,入栈基本类型 a 变量在栈中被创建b() 方法被调用,入栈引用类型 b 在栈中被创建User 类型的实例在堆中被创建将 User 实例的内存地址指向引用类型 bb() 方法执行结束,b 变量销毁,断开对 User 实例的引用,出栈a() 方法执行结束,a 变量销毁,出栈垃圾回收将不再被引用的 User 实例回收掉main() 方法执行结束,出栈程序执行结束打完收工。技术聊完了,下面我们聊点正事儿!咳咳,趁着现在粉丝还不是太多,给早期关注的读者送点福利,关注「做个开发者」。在公众号文章下方留言,获赞最多的三位读者每人送一本我的新书《Spring Boot趣味实战课》,七月三十一号开奖。另外,这次活动是双管齐下,公众号和微博同步进行。且两个活动可以累加,如果你都参加,那么中奖几率直接翻倍。并且支持定制签名(如果不嫌我字丑,哈哈)。微博上的活动也很简单,关注「@水镜不酷」并转发下图中的微博即可。对了,如果你真的中了两本,可以将其中一本兑换成现金,按照目前京东促销价折算为 60 微信红包(目前京东到手 57.8 元)。行了,别的不多说了大家帮忙转发一下吧。
对于任何一门语言,要想达到精通的水平,研究它的执行原理(或者叫底层机制)不失为一种良好的方式。在本篇文章中,将重点研究java源代码的执行原理,即从程序员编写JAVA源代码,到最终形成产品,在整个过程中,都经历了什么?每一步又是怎么执行的?执行原理又是什么?.....当然,本篇文章的粒度可能稍微侧重于宏观方面,更细粒度的技术分析,需要在接下来的该系列文章中与大家分享....一 编写java源程序java源文件:指存储java源码的文件;当前比较主流的JAVA IDE?(1)Intellij IDEA(首推荐)(2)Eclipse先来看看如下代码://MyTest被public修饰,故存储该java源码的文件名为MyTestpublic class MyTest {public static void main(String[] args){System.out.println("Test Java execute process.");}}//由于MyTest被public修饰了,故Class A不能用public修饰class A{}//由于MyTest被public修饰了,故Class B不能用public修饰class B{}(1)java源文件名就是该源文件中public类的名称(2)一个java源文件可以包含多个类,但只允许一个类为public二 编译java源代码当java源程序编码结束后,就需要编译器编译,安装好jdk后,我们打开jdk目录,有两个.exe文件,即javac.exe(编译源代码,即.java文件)和java.exe(执行字节码,即.class文件)1.切换到MyTest.java文件夹2.javac.exe编译MyTest.java编译后,发现e:\Blogs 目录多了以class为后缀的文件:A.class,B.class和MyTest.classTip:当javac.exe编译java源代码时,java源代码有几个类,就会编译成一个对应的字节码文件(.class文件),其中,字节码文件的文件名就是每个类的类名。需要注意的是,类即使不在源文件中定义,但被源文件引用,编译后,也会编程相应的字节码文件,如类A引用类C,但类C不定义在类A的源文件中,编译后,类C也被编译成对应的字节码文件C.class三 执行java源文件执行java源文件,用java.exe执行即可到现在,java源程序基本执行结果,并正确打印我们期望的结果,那么,如上的步骤,我们可以总结如下:如上总结,已经抽象化了在JVM中的执行,接下来,我们将分析,字节码文件(.calss文件)如何在虚拟机中一步一执行的。四 JVM如何执行字节码文件(一) 装载字节码文件当.java源码被javac.exe编译器编译成.class字节码文件后,接下来的工作就交给JVM处理,JVM首先通过类加载器(ClassLoader)将class文件和相关Java API加载装入JVM,以供JVM后续处理。在该阶段中,涉及到如下一些基本概念和知识。1.JDK,JRE和JVM关系(1)JDK(Java Development Kit),Java开发工具包,主要用于开发,在JDK7前,JDK包括JRE(2)JRE(Java Runtime Environment),Java程序运行的核心环境,包括JVM和一些核心库(3)JVM(Java Virtual Machine),VM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的,是JRE核心模块。2.JVMJVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机虚拟机的主要任务是装载class文件并执行其中的字节码,不同的Java虚拟机中,执行引擎可能由不同的实现,大致有如下几种引擎:一次性解释字节码引擎即时编译引擎自适应优化器关于虚拟机的实现方式,采用软件方式、硬件方式和软件硬件结合方式,这个要根据具体厂商而定。3.什么是ClassLoader虚拟机的主要任务是装载class文件并执行其中的字节码,而class文件是由虚拟机的类加载器(ClassLoader)完成的,在一个Java虚拟机,有可能存在多个类加载器。任何java运用程序,可能会使用两种类加载器,即启动类加载器(bootstrap)和用户自定义类加载器。启动类加载器是Java虚拟机唯一实现的一部分,它又可分为原始类装载器,系统类装载器或默认类装载器,它的主要作用是从操作系统的磁盘装载相应的类,如Java API类等。用户自定义装载类,按照用户自定义的方式来装载类。(二)将字节码文件存储在JVM内存区当JAVA虚拟机运行一个程序时,它需要内存来存储许多东西,如字节码,从已装载的class文件中得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量以及运算的中间结果等,这些相关信息被组织到“运行时数据区”。根据厂商的不同,在Java虚拟机中,运行时数据区也有所不同,有些运行时数据区由线程共享,有些只能由某个特定线程共享。运行时数据区大致可分几个区:方法区,堆区,栈区,PC寄存器区和本地方法栈区。在该阶段中,涉及到如下基本概念和知识。1.方法区方法区用来存储解析被加载的class文件的相关信息。当虚拟装载一个class文件后,它会从这个class文件包含的二进制数据中解析类型信息,然后将该相关信息存储到方法区中。2.堆堆是用来存储相关引用类型的,如new对象。当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中。3.PC寄存器PC寄存器主要用来存储线程。当新创建一个线程时,该线程都将得到一个自己的PC寄存器(程序计数器)以及一个java栈。Java虚拟机没有寄存器,其指令集使用Java栈来存储中间数据。4.栈区栈区主要用来存储值类型的,如基本数据类型,需要注意的时,String为引用类型,是存在堆中的。Java栈是由许多栈帧组成的,一个栈帧包含一个Java方法调用的状态,当线程调用一个方法时,虚拟机压入一个新的栈帧到该线程的Java栈中,当该方法返回时,这个栈帧从Java栈中弹出。(三)执行引擎与运行时数据区交互运行时数据区为执行引擎提供了执行环境和相关数据,执行引擎通过与运行时数据区交互,从而获取执行时需要的相关信息,存储执行的中间结果等(四)执行引擎与本地方法接口当要执行本地方法时,执行引擎将调用本地方法接口来获取相关OS本地方法,需要注意的是,本地方法与操作系统强耦合的。(五)JVM在具体操作系统上执行JVM通过调用本地接口来获取本地方法,从而实现在具体的平台上执行,如在Linux系统上执行,在Window系统上执行和在Unix系统上执行。五 参考文献【01】深入Java虚拟机(原书第2版)(美)Bill Venners 著【02】Core Java Volume I - Fundamententals(10th Edition) (美) Cay S.Horstmann【03】Core Java Volume I - Advanced Features(10th Edition) (美) Cay S.Horstmann来源:博客园作者:Alan_beijing

我要回帖

更多关于 java程序运行的过程 的文章

 

随机推荐