java代码如何运行_01_Java代码是怎么运行的?

第一次耐心的看JVM的相关概念,弱小又可怜。。。

JDK(Java Development Kit)与JRE(Java Runtime Environment):

JDK包含 开发诊断工具 以及 JRE,JRE包含Java虚拟机以及Java核心类库;

Java的运行:

开发工具中运行,命名行中运行,双击Jar包中运行,或者在网页中运行;

但都离不开JRE

C++的运行:

代码直接编译成 CPU 所能理解的代码格式,也就是机器码。

Java为什么需要在虚拟机上运行:

Java源代码的具体运行流程;

1:设计一个面向 Java 语言特性的虚拟机;

2:并通过编译器将 Java 程序转换成该虚拟机所能识别的指令序列:

Java字节码(class文件);

3:当变成Java字节码后,它可以在不同平台的虚拟机运行;

4:虚拟机的这种托管环境拥有 自动内存管理与垃圾回收的功能;以及

数组越界、动态类型、安全权限等等的动态检测的额外功能等等;

虚拟机(HotSpot 虚拟机)是如何运行Java字节码文件的?

1:执行 Java 代码首先需要将它编译而成的 class 文件加载到 Java 虚拟机中。

2:加载后的 Java 类会被存放于方法区(Method Area)中。

3:实际运行时,虚拟机会执行方法区内的代码。

4:Java 虚拟机同样也在内存中划分出堆和栈来存储运行时数据。

5:每当调用一个 Java 方法,则当前线程的 Java 方法栈中生成一个栈帧(Java 虚拟机不要求栈帧在内存空间里连续分布),用以存放局部变量以及字节码的操作数;

6:当退出当前执行的方法时,不管是正常返回还是异常返回,均会弹出当前线程的当前栈帧,并将之舍弃。

栈的成员:

Java 方法栈;

本地方法栈:面向本地方法(用 C++ 写的 native 方法);

PC 寄存器:存放各个线程执行位置;

a890071c6aa8

Java虚拟机.png

从硬件视角来看,Java 字节码无法直接执行。

因此,Java 虚拟机需要将字节码翻译成机器码。

第一种是解释执行,即逐条将字节码翻译成机器码并执行;

第二种是即时编译(Just-In-Time compilation,JIT),即将一个方法中包含的所有字节码编译成机器码后再执行。

HotSpot 默认采用混合模式,综合了解释执行和即时编译两者的优点。

a890071c6aa8

解释编译.png

运行效率:

对于占据大部分的不常用的代码,我们无需耗费时间将其编译成机器码,而是采取解释执行的方式运行;

另一方面,对于仅占据小部分的热点代码,我们则可以将其编译成机器码,以达到理想的运行速度。

理论上讲,即时编译后的 Java 程序的执行效率,是可能超过 C++ 程序的。

这是因为与静态编译相比,即时编译拥有程序的运行时信息,并且能够根据这个信息做出相应的优化。

为了满足不同用户场景的需要,HotSpot 内置了多个即时编译器:C1、C2 和 Graal。

Graal 是 Java 10 正式引入的实验性即时编译器,这里暂不做讨论。之所以引入多个即时编译器,是为了在编译时间和生成代码的执行效率之间进行取舍。

C1 又叫做 Client 编译器,面向的是对启动性能有要求的客户端 GUI 程序,采用的优化手段相对简单,因此编译时间较短。

C2 又叫做 Server 编译器,面向的是对峰值性能有要求的服务器端程序,采用的优化手段相对复杂,因此编译时间较长,但同时生成代码的执行效率较高。

从 Java 7 开始,HotSpot 默认采用分层编译的方式:热点方法首先会被 C1 编译,而后热点方法中的热点会进一步被 C2 编译。

为了不干扰应用的正常运行,HotSpot 的即时编译是放在额外的编译线程中进行的。HotSpot 会根据 CPU 的数量设置编译线程的数目,并且按 1:2 的比例配置给 C1 及 C2 编译器。

在计算资源充足的情况下,字节码的解释执行和即时编译可同时进行。编译完成后的机器码会在下次调用该方法时启用,以替换原本的解释执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值