前言

本文记录日常学习《深入理解Java虚拟机》,不知道为啥感觉看一遍也就过了,喜欢动动手理解理解,这样才有点感觉,静不下心来的时候,看书抄书也可以用这个办法。

一、什么是JIT(Just In Time Compiler)即时编译器

在虚拟机中(Sun HotSpot),Java程序最初是通过解释器执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”(Hot Spot Code)。为了提高热点代码的执行效率,在运行时,虚拟机会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler)。

Java虚拟机规范并没有规定java虚拟机内必须要有即时编译器存在,更没有限定和指导即时编译器应该如何去实现。但是即时编译器的好坏、代码优化程度的高低却是衡量一款商用虚拟机优秀与否的最关键指标之一,它也是虚拟机中最核心最能体现虚拟机水平的部分。

二、JVM内置的两个即时编译器

C1编译器:Client Compiler
C2编译器:Server Compiler

HotSpot虚拟机,默认采用解释器与其中一个编译器直接配合的方式工作,程序使用哪个编译器,取决于虚拟机运行的模式,HotSPot虚拟机会根据自身版本与宿主机器的硬件性能自动选择运行模式。也可以使用“-client”和“-server”参数去强制指定虚拟机运行在Client模式还是Server模式。

[root@ip-10-0-0-90 ~]# java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode) [root@ip-10-0-0-90 ~]# java -Xint -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, interpreted mode) [root@ip-10-0-0-90 ~]# java -Xcomp -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, compiled mode)

三、JVM的分层策略

第0层:程序解释执行,解释器不开启性能监控功能(Profiling),可触发第一层编译。
第1层:也称C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑。
第2层(或2层以上):也称C2编译,将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

分层策略在JDK8是默认开启的,C1编译可获取更高的编译速度,C2编译可获取更好的编译质量。

四、编译对象和触发条件

编译对象:

1)被多次调用的方法
2)被多次执行的循环体

触发条件:

1)基于采样的热点探测
采用这种方法的虚拟机会周期性的检查各个线程的栈顶,如果发现某个或某些方法经常出现在栈顶,那这个方法就是“热点方法”。

2)基于计数器的热点探测
采用这种方法的虚拟机会为每个方法(或代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的值就认为他是“热点方法”。

五、JIT编译方式和OSR编译方式

JIT编译方式

方法调用触发的编译,编译器会以整个方法作为编译对象,这种编译也是虚拟机中标准的JIT编译方式。

OSR编译方式

循环体调用触发的编译即使是由循环体触发的,但编译器会以整个方法(而不是单独的循环体)作为编译对象。这种编译方式因为编译发生在方法执行过程中,因此形象的称为栈上替换(On Stack Replacement)简称OSR编译,即方法栈帧还在栈上,方法就被替换了。

六、方法计数器和回边计数器

在HotSpot虚拟机中,使用的是基于计数器的热点探测,他为每个方法准备了两类计数器,方法调用计数器(Incocation Counter) 和回边计数器(Back Edge Counter)。这两个计数器都有一个阀值,当计数器超过了这个阀值,就会触发JIT编译。

1)方法调用计数器

用于统计方法被调用的次数,默认阀值为Client模式下:1500次,Server模式下10000次;这个阀值可以通过虚拟机参数-XX:CompileThreshold设定。当一个方法被调用时,会先检查该方法是否存在被JIT编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加1,然后判断方法调用启与回边计数器值之和是否超过方法调用计数器的阀值,如果超过阀值,那么将会向即时编译器提交该方法的代码编译请求。

在默认情况下,执行引擎不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成。当编译工作完成后,这个方法的调用入口地址就会被系统自动改写成新的,下一次调用该方法时就会使用已编译的版本。

注:
如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是相对执行频率,即在一段时间之内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让他提交给即时编译器,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(Counter Half Life Time)。进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样只要系统运行时间足够长,绝大部分方法都会被编译成本地代码。另外,可以使用-XX:CounterHalflifeTime参数设置半衰周期的时间,单位为s。

2)回边计数器

回边计数器,他的作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”(back Edge),建立回边计数器统计的目的就是为了触发OSR编译。

想买保时捷的运维李先生学Java性能之 JIT即时编译器的更多相关文章

  1. 想买保时捷的运维李先生学Java性能之 运行时数据区域

    前言 不知道自己不知道,不知道自己知道,知道自己不知道,知道自己知道,目前处于知道自己不知道这个阶段,很痛苦啊,干了4年了运维,是一个坎.越来越发觉想要走得远,还是得扎根底.   一.运行时数据区域 ...

  2. 想买保时捷的运维李先生学Java性能之 生存与毁灭

    一.判断对象是否存活     1.引用计数算法   给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1:当引用失效时,计数器的值就减1:任何时刻计数器为0的对象是不可能再被使用的.引用计 ...

  3. 想买保时捷的运维李先生学Java性能之 垃圾收集算法

    前言 从原来只知道-Xms.-Xmx是设置内存的,到现在稍微理解了一些堆内存等Java虚拟机的一些知识.明白了技术这一个东西还是得要有输入才能实践,原理与实践要相辅相成,后续把JVM的监控好好总结一下 ...

  4. 想买保时捷的运维李先生学Java性能之 垃圾收集器

    前言 垃圾收集算法是内存回收的方法论:垃圾收集器是内存回收的具体实现.Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商.不同版本的虚拟机所提供的垃圾收集器都有很大的差别,并且 ...

  5. Linux运维不可不知的性能监控和调试工具

    Linux运维不可不知的性能监控和调试工具 1 nagios Nagios是一个开源监控解决方案,我觉得他可以监控一切 ,可以看一下我以前的文章:NAGIOS 2 ps #用来查看程序的运行情况 ps ...

  6. 从零起步做到Linux运维经理, 你必须管好的23个细节

    “不想成为将军的士兵,不是好士兵”-拿破仑 如何成为运维经理? 一般来说,运维经理大概有两种出身:一种是从底层最基础的维护做起,通过出色的维护工作,让公司领导对这个人非常认可,同时对Linux运维工作 ...

  7. 从零起步做到Linux运维经理,你必须管好的23个细节

    不想成为将军的士兵,不是好士兵-拿破仑 如何成为运维经理?成为运维经理需要什么样的能力?我想很多运维工程师都会有这样的思考和问题. 如何成为运维经理.一般来说,运维经理大概有两种出身,一种是从底层最基 ...

  8. 转:linux运维工程师

    运维中关键技术点解剖:1 大量高并发网站的设计方案:2 高可靠.高可伸缩性网络架构设计:3 网站安全问题,如何避免被黑?4 南北互联问题,动态CDN解决方案:5 海量数据存储架构 一.什么是大型网站运 ...

  9. 面试 Linux 运维工作至少需要知道哪些知识?

    前言 我们已经发过不少 Linux 面试题,但是单独的面试题总感觉会过于零碎,没有体系化内容给人的帮助大. 知乎上有这样一个问题:一个新手面试 Linux 运维工作至少需要知道哪些知识?其中有一个答案 ...

随机推荐

  1. 常用的Websocket技术一览

    1. 前言 Websocket是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据 ...

  2. Nginx反代MogileFS集群

    上一篇博文我们主要聊了下分布式文件系统MogileFS的组件以及部署使用,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13677279.html:今天我们主要 ...

  3. StarUML 3.1.0 for Windows 10

    StarUML 3.1.0 for Windows 10 1.下载 StarUML 3.1.0 http://staruml.io/download 2.安装 npm 到官网下载安装 windows版 ...

  4. 微信小程序直播接入

    申请开通小程序直播 1.申请小程序直播有以下几个硬性指标: 1. 满足小程序18个开放类目 2. 主体下小程序近半年没有严重违规 3. 小程序近90天内有过支付行为 4. 主体下公众号累计粉丝数大于1 ...

  5. selenium执行js--并绕过webdriver监测常见方法

    目录 selenium执行js 常见的selenium监测手段 常用绕过selenium监测1 常用绕过selenium监测2 常用绕过selenium监测3 selenium执行js 优点:直接调用 ...

  6. Spring Boot 知识清单(一)SpringApplication

    爱生活,爱编码,微信搜一搜[架构技术专栏]关注这个喜欢分享的地方.本文 架构技术专栏 已收录,有各种JVM.多线程.源码视频.资料以及技术文章等你来拿. 一.概述 目前Spring Boot已经发展到 ...

  7. Java JVM参数在idea里面配置

    找到你需要配置的启动类选择 接着点击Edit Configurations 在VM options里面配置就完成了

  8. 最新版PyCharm激活教程!有效期至2089年!

    Python的编译器有很多,像Pycharm.VsCode.Jupyter...哪个好用不做评价,各有各的优点!用过PyCharm的同学都知道,PyCharm有两大版本,专业版和社区版,专业版相当于社 ...

  9. python_多级菜单_纯循环与分支

    源代码: #!/usr/bin/python3 __author__ = 'beimenchuixue' __blog__ = 'http://www.cnblogs.com/2bjiujiu/' d ...

  10. Centos-目录或文件拷贝-cp

    cp 拷贝或者备份文件或者目录 相关选项 -a 拷贝目录保存文件所有信息 -r  递归拷贝目录 -d 保留连接 -p 保留修改时间和存取权限 -i 有同名提醒是否覆盖 相关应用 1. 备份文件 cp ...