Java代码运行的方式

1:在开发工具中运行
2:双击 jar 文件运行
3:在命令行中运行
4:在网页中运行

上述运行方式都离不开 JRE,也就是 Java 运行时环境。实际上 JRE 仅包含运行 Java 程序的必须组件,包括 Java 虚拟机以及 Java 核心类库等。Java 程序员经常接触到的 JDK 同样包含了 JRE,并且还附带了一系列开发和诊断工具。

为什么 Java 要在虚拟机里运行

Java 是一门高级程序语言,语法复杂,抽象程度高,因此直接在硬件上运行并不现实。所以,在 Java 程序运行之前,需要对其进行转换。

设计一个面向 Java 语言的特性的虚拟机,并通过编译器将 Java 程序转换成该虚拟机所能识别的指令程序,也叫 Java 字节码。之所以叫做字节码,是因为 Java 字节码指令的操作码被固定为一个字节。

使用虚拟机的好处

Java 虚拟机也可以由硬件直接实现,但是更为常见的是基于软件实现。

如果一个 Java 程序被转换成 Java 字节码,那么他便可以在不同平台上的 Java 虚拟机实现里运行。这就是通常所说的:一次编译,到处运行。

虚拟机的另一个好处就是它提供了一个托管环境。这个托管环境代替我们处理一些代码中冗长而且容易出错的代码。最明显的使用就是自动内存管理和垃圾回收。托管环境还提供了诸如数组越界,动态类型,安全权限等等动态监测。

Java 虚拟机如何运行 Java 字节码

下面以标准 JDK 中的 HotSpot 虚拟机为例,从虚拟机以及底层硬件两个角度进行分析。

从虚拟机的视角来看,首先将 Java 代码编译成 class 文件加载到 Java 虚拟机中。加载后的 Java 类会被存放于方法区,实际运行时,虚拟机会执行方法区的代码。

Java 虚拟机在内存中划分出堆和栈来存储运行时的数据。对于栈, Java 虚拟机会把其细分为面向 Java 方法的 Java 方法栈,面向本地方法(用 C++ 写的 native 方法)的本地方法栈,以及存放各个线程执行位置的 PC 寄存器。

在虚拟机运行过程中,每当调用进入一个 Java 方法, Java 虚拟机会在当前线程的 Java 方法栈中生成一个栈帧,用以存放局部变量以及字节码的操作数。

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

从硬件的视角来看,Java 字节码无法直接执行,因此 Java 虚拟机需要将字节码翻译成机器码。

翻译的形式有两种,一种是解释执行,即逐条将字节码翻译成机器码执行;一种是即时编译,即将一个方法中包含的所有字节码编译成机器码后再执行。

解释执行的优势在于无需等待编译,及时编译的优势在于实际运行速度会更快。HotSpot 默认采用混合模式,综合了解释执行和即时编译两者的优点。它会先解释执行字节码,而后将其中反复执行的热点代码,以方法为单位进行即时编译。

Java 虚拟机的运行效率

HotSpot 采用了多种技术来提升启动性能以及峰值性能,即时编译就是其中最重要的技术之一。

为了满足不同用户场景的需要,HotSpot 内置了多个即时编译器:C1,C2 和 Graal。Graal 是 Java 10 正式引入的实验性即时编译器,后续再总结。引入多个即时编译器,是为了在编译时间和生成代码的执行效率之间进行取舍。

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

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

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

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

问答

Q:对于发布一次就长时间运行的程序,为什么不选择直接将 Java 字节码编译成机器码

事实上 JVM 却是有考虑做 AOT 的这种事情。AOT 能够在线下将 Java 字节码编译成机器码,主要用来解决启动性能不好的问题。其实线下编译和即时编译都一样,至多一两个小时后该编译的都已经编译完成了。另外,即时编译器因为有程序运行时信息,优化效果更好,也就是说峰值性能更好。

Q:如何区分热点代码和非热点代码

关于热点代码的统计有两种算法:一种是基于采样的热点探测,一种是基于计数器的热点探测。基于计数器的热点探测又有两个计数器:一种是方法调用计数器,一种是回边计数器,他们在 C1 和 C2 中有不同的阈值。默认的分层编译应该是达到两千调用 C1,达到一万五调用 C2。一般采用的都是基于计数器的热点探测。

Q:对于 JVM 的及时编译,当方法体中有很多 if,else if 这样的判断,如何编译

JVM 有两种编译方式,一种是对整个方法进行编译,一种是对热循环进行编译。无论哪种,都要比 if else 的粒度大。

总结

本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。

关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。

01 Java 代码是怎么运行的的更多相关文章

  1. 听说你还不知道Java代码是怎么运行的?

    作为一名Java程序员,我们需要知道Java代码是怎么运行的.最近复习了深入理解Java虚拟机这本书,做了一下笔记,希望对大家有帮助,如果有不正确的地方,欢迎提出,感激不尽. java 代码运行主要流 ...

  2. JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇

    JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇 作为一个使用Java语言开发的程序员,我们都知道,要想运行Java程序至少需要安装JRE(安装JDK也没问题).我们也知道我们Java程序 ...

  3. 《深入理解Java虚拟机》-Java代码是如何运行的

    问题一:Java与C++区别 1.Java需要运行时环境,包括Java虚拟机以及Java核心类库等. 2.C++无需额外的运行时,通常编译后的代码可以让机器直接读取,即机器码 问题一:Java为什么要 ...

  4. Java代码是怎么运行的

    前言.... 作为一名 Java 程序员,你应该知道,Java 代码有很多种不同的运行方式.比如说可以在开发工具中运行,可以双击执行 jar 文件运行,也可以在命令行中运行,甚至可以在网页中运行.当然 ...

  5. Java代码在本地运行没有问题。上传到阿里云服务器后。出现了中文乱码解决

    java -Dfile.encoding=UTF-8 -jar project.jar

  6. MVC框架的理解(配置文件一次编写,所有的java代码都可以运行)

  7. JAVA_HOME path classpath 以及cmd编译运行java代码

    JAVA_HOME PATH CLASSPATH 三者的区别:安装完jdk之后,首先在环境变量里面添加JAVA_HOME ,例如安装路径为C:\Program Files\Java\jdk1.6.0_ ...

  8. 用DOS命令来运行Java代码

    用DOS命令来运行Java代码.. ----------------- Demo.java public class Demo { public static void main(String[] a ...

  9. Java基础之用记事本编辑java代码运行,并且打成jar包后运行

    使用记事本写java代码 1.在d盘新建一个记事本,名字叫做zhanzhuang.java,会询问不可用,是否继续,点击是 2.在里面编辑就如下内容,注意文件的名字要和 class 后面的名字相对应 ...

随机推荐

  1. MyBatis关联查询、多条件查询

    MyBatis关联查询.多条件查询 1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Cla ...

  2. <Android Framework 之路>多线程

    多线程编程 JAVA多线程方式 1. 继承Thread线程,实现run方法 2. 实现Runnable接口 JAVA单继承性,当我们想将一个已经继承了其他类的子类放到Thread中时,单继承的局限就体 ...

  3. tomcat配置https 和 http强制跳转https

    https是http+ssl的可进行加密传输,身份认证的网络协议,防止数据在传输过程中被窃取.因此,https将得到越来越广泛的应用,下面是如何配置tomcat服务器让http自动转到https的步骤 ...

  4. ./theHarvester.py -d baidu.com -l 100 -b google

    ./theHarvester.py -d baidu.com  -l 100 -b google

  5. jsoup获取网页属性

    package com.open1111.jsoup; import org.apache.http.HttpEntity;import org.apache.http.client.methods. ...

  6. hdu 3861 The King’s Problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  7. 浅谈iOS学习之路

    转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...

  8. UVA 11988 Broken Keyboard (链表)

    简单题,题目要求显然是很多次插入,所以是链表. 插入两个语句,nxt[i] = nxt[u] 表示 i结点指向u的后继, nxt[u] = i表示把u的后继设成i. 设置一个头结点,指向一个不存在的结 ...

  9. JS实现单向链表、双向链表、循环链表

    https://cloud.tencent.com/developer/article/1114246 链表存储有序的元素的集合,但是和数组不同的是,链表中的元素在内存中的存储并不是连续的.每一个链表 ...

  10. Beta冲刺(周四)

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1 这个作业要求在哪里 https://edu.cnblo ...