JVM优化Java代码时都做了什么?
专栏的前几篇文章了解了JVM的内存模型,GC调优的思路,让我们对于Java底层有了一定的了解,那么采用这种思路去提高JVM的性能,减少JVM额外消耗的同时,JVM究竟做了哪些工作,使我们的Java代码得到了优化呢?
今天主要将关于Java的生命周期和JVM运行时候的优化方法进行一下描述,让大家知道JVM优化时,究竟在Java运行中,JVM究竟做了什么???
简述
Java程序运行起来之后,JVM对代码的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。运行时优化主要是解释执行和动态编译通用的一些机制,比如说:锁机制(如偏斜锁)、内存分配机制(如TLAB)等。除此之外,还有一些专门用于优化解释执行效率的,比如说模版解释器、内联缓存( inline cache,用于优化虚方法调用的动态绑定)。
之前的专栏中讲到Java程序在JVM中执行的时候,首先会以方法为module转化为JVM可以识别的数据结构,直接运行在底层硬件上。采用的优化方式主要如下:
- 方法内联
- 逃逸分析
- 基于程序运行profile的投机性优化
主要来解释一下第三条:比如有一条instanceof指令,在编译之前的执行过程中,测试对象的类一直是同一个,那么即时编译器可以假设编译之后的执行过程中还会是这一个类,并且根据这个类直接返回instanceof的结果。如果出现了其他类,那么就抛弃这段编译后的机器码,并且切换回解释执行。
JVM的优化方式仅仅作用在运行应用代码的时候,如果应用代码本身阻塞了,比如说并发时等待另一线程的结果,这就不再JVM的优化范畴。
今天专栏侧重于:
- Java的生命周期
- JIT及其调优
知识扩展
1、Java生命周期
示意图如下:
前面讲到Java在编译的时候,将代码转换为字节码,这样屏蔽了不同硬件的差异,然后由JVM负责完成从字节码到机器码的转化。
在编译期间会进行少量类似常量折叠之类的优化,只要利用反编译工具就可以直接查看细节。
javac优化与JVM内部优化存在关联,毕竟它负责了字节码的生成。
今天的重点是JVM运行时的优化,通常情况JIT和解释器一起作用,参考下图:
JVM会动态决定哪些方法被编译,哪些方法被执行,即使是已经编译过的代码,也可能不再是热点,会被移除。
JVM内存模型中存在Java虚拟机栈,对应一个线程,且线程本身拥有不断由JVM管理的入栈,出栈的栈帧,控制方法的进入与出去。而优化的细节,就可以从GC调优思路入手去回顾,通过不断的编译,检验方法的热点程度,也就是我们之前的新生代逐步走向老年代的过程,这也就对应了,没有价值的方法会被Code Cache清除这一过程了。
在解释器和编译器中,也会进行一些通用优化:
- 锁优化
- Intrinsic机制,或者叫内建方法,指的是JDK将一些重要方法,像java.util直接进行定制实现
这样的做的意义在于,不同的指令在不同的CPU上执行的效率是不同的,为了充分发挥硬件的能力,就需要定制操作。
而JIT,则是优化工作的承担者。它会对我们程序中的代码进行热点分析,通过方法调用的计数,甄别出热点代码,并且将其转化为本地代码。同时也会将一些调用频度不够转化为本地代码,但是却执行递归循环的代码,也进行优化。
总结,JVM将代码执行计数器反馈给JVM,定位热点代码,并且转化为本地代码。但实际上,JIT机制更加复杂,涉及到:逃逸分析,循环展开,方法内联等等。
探查优化的具体发生情况
- 打印编译发生的细节
-XX:+PrintCompilation
- 输出更多编译细节
-XX:UnlockDiagnosicVMOptions
-XX:+LogCompilation
-XX:LogFile=<your_fle_path>
- JVM会生成一个xml形式的文件,另外LogFile选项是可选的不指定则会输出到
hotspot_pid.log
- 打印内联的发生,可利用下面的诊断选项,也需要明确解锁
-XX:+PrintInlining
- 如何知晓Code Cache的使用状态呢?
很多工具都已经提供了具体的统计信息,比如,JMC、JConsole之类,我也介绍过使用NMT监控其使用。
触手可及的调优角度和手段
- 调整热点代码门限值
我曾经介绍过JIT的默认门限,server模式默认10000次,client是1500次。门限大小也存在着调优的可能,可以使用下面的参数调整;与此同时,该参数还可以变相起到降低预热时间的作用。
-XX:CompileThreshold=N
很多人可能会产生疑问,既然是热点,不是早晚会达到门限次数吗?这个还真未必,因为JVM会周期性的对计数的数值进行衰减操作,导致调用计数器永远不能达到门限值,除了可 以利用CompileThreshold适当调整大小,还有一个办法就是关闭计数器衰减。
-XX:-UseCounterDecay
如果你是利用debug版本的JDK,还可以利用下面的参数进行试验,但是生产版本是不支持这个选项的。
-XX:CounterHalfLifeTime
- 调整Code Cache大小
我们知道JIT编译的代码是存储在Code Cache中的,需要注意的是Code Cache是存在大小限制的,而且不会动态调整。这意味着,如果Code Cache太小,可能只有一小部分代码可以被JIT编译,其他的代码则没有选择,只能解释执行。所以,一个潜在的调优点就是调整其大小限制。
-XX:ReservedCodeCacheSize=
当然,也可以调整其初始大小。
-XX:InitialCodeCacheSize=
注意,在相对较新版本的Java中,由于分层编译(Tiered-Compilation)的存在,Code Cache的空间需求大大增加,其本身默认大小也被提高了。
- 调整编译器线程数,或者选择适当的编译器模式
JVM的编译器线程数目与我们选择的模式有关,选择client模式默认只有一个编译线程,而server模式则默认是两个,如果是当前最普遍的分层编译模式,则会根据CPU内核数目计 算C1和C2的数值,可以通过下面的参数指定的编译线程数。
-XX:CICompilerCount=N
在强劲的多处理器环境中,增大编译线程数,可能更加充分的利用CPU资源,让预热等过程更加快速;但是,反之也可能导致编译线程争抢过多资源,尤其是当系统非常繁忙时。例如,系统部署了多个Java应用实例的时候,那么减小编译线程数目,则是可以考虑的。
生产实践中,也有人推荐在服务器上关闭分层编译,直接使用server编译器,虽然会导致稍慢的预热速度,但是可能在特定工作负载上会有微小的吞吐量提高。
- 其他一些相对边界比较混淆的所谓"优化"
比如,减少进入安全点。严格说,它远远不只是发生在动态编译的时候,GC阶段发生的更加频繁,你可以利用下面选项诊断安全点的影响。
-XX:+PrintSafepointStatisics
‑XX:+PrintGCApplicationStoppedTime
注意,在JDK 9之后,PrintGCApplicationStoppedTime已经被移除了,你需要使用“-Xlog:safepoint”之类方式来指定。
很多优化阶段都可能和安全点相关,例如:
在JIT过程中,逆优化等场景会需要插入安全点。
常规的锁优化阶段也可能发生,比如,偏斜锁的设计目的是为了避免无竞争时的同步开销,但是当真的发生竞争时,撤销偏斜锁会触发安全点,是很重的操作。所以,在并发场景中偏斜锁的价值其实是被质疑的,经常会明确建议关闭偏斜锁。
-XX:-UseBiasedLocking
JVM优化Java代码时都做了什么?相关推荐
- asp java 变量_ASP_用stack变量优化Java代码, java程序包含了大量的对象 - phpStudy...
用stack变量优化Java代码 java程序包含了大量的对象,我们需要了解它们是从哪里被访问的,变量存储于何处对程序的性能有显著的影响--尤其是某些需要被频繁访问的变量. 我们写一个Java类,在其 ...
- java+set+split_阿里资深工程师教你如何优化 Java 代码!
原标题:阿里资深工程师教你如何优化 Java 代码! 作者 | 王超 责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见 ...
- 写java代码时的注意事项_从方法返回Java 8的可选项时的注意事项
写java代码时的注意事项 Java 8引入的Optional类一直是该语言版本引入的最具争议的功能之一. 尽管我喜欢这个新的Java类的东西比不喜欢的东西多,但在Java方法中将其用作return类 ...
- 运行java提示找不到符号_运行java代码时出现找不到符号错误怎么解决
运行java代码时出现找不到符号错误怎么解决 发布时间:2020-06-23 11:37:00 来源:亿速云 阅读:113 作者:Leah 运行java代码时出现找不到符号错误怎么解决?针对这个问题, ...
- 运行Java代码时,遇到java.io.IOException: parseAlgParameters failed: PBE AlgorithmParameters not available
运行Java代码时,遇到parseAlgParameters failed: PBE AlgorithmParameters not available java.io.IOException: pa ...
- 提升效率:优化Java代码的35个小技巧
每天早晨,干货准时奉上! 本文作者:萌小Q 来源: www.cnblogs.com/Qian123/p/6046096.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方 ...
- java代码_阿里资深工程师教你如何优化 Java 代码!
作者 | 王超责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见道无终穷,愈探愈深,必使精白无一毫不彻方可. 代码中的& ...
- 阿里资深工程师教你如何优化 Java 代码!
作者 | 王超 责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见道无终穷,愈探愈深,必使精白无一毫不彻方可. 代码中的 ...
- IntelliJ IDEA 编译Java代码时,中文乱码问题
有很多文章介绍了这些方法,都一般都是只有前两项,或是只有第三项.这里全放上吧,做个记录. 在导入别人的项目或是自己以前的项目时,在 Build Project 时,会出现因为中文注释的乱码,所导致的编 ...
最新文章
- javascript中五句话
- PyQt5 笔记4 -- 多线程
- mac 10.11 安装mysql5.7.10压缩版
- otb100matlab,ECO for tracking 在 OTB100 基准测试和 VOT2016 数据集中的实验结果
- (王道408考研数据结构)第五章树-第四节4:红黑树基本概念及操作
- 安卓平台下的即时通讯
- STM32使用大彩串口屏程序框架使用总结
- YOLO系列目标检测数据集大全
- grpc系列1-K8S集群,VIP,grpc._channel._InactiveRpcError connection reset by peer解决方案 Paddleserving服务化部署
- css样式中的vw什么意思,css vw是什么单位
- 三颗种子开发系统源码
- 2020牛客寒假算法基础集训营3 B	牛牛的DRB迷宫II二进制详解
- 二元置信椭圆r语言_R语言 第4章 初级绘图(6)
- .Net MAUI 安卓状态栏透明、半透明、全屏
- ssh 免账号密码登录
- 覆盖式理解Android 消息处理机制(带源码解析)
- 行云管家V4.9正式发布:监控全面提升,首页、主机详情大幅优化,新增大量实用功能.md...
- 操作系统-Linux内核系列
- 城市公交查询系统c语言,城市公交查询系统城市公查询系统.doc
- 泰拉瑞亚安装、运行教程
热门文章
- 杭电和苏大计算机考研,江苏省各高校“排行榜”出炉,江苏大学10名开外,南大当属第一!...
- 内置Prisemi保护IC P14C1N,安克、真我、万魔、红米等全新产品TWS耳机上应用,现推荐安克举例。
- vivo2020届春季校园招聘手机屏幕解锁模式
- (转)Android闪屏问题解决思路
- Sentinel(四)限流算法-令牌桶算法
- mapbox图形绘画以及polygon信息提取
- 2021年PC电脑网站接入微信登陆支付精讲--1小时自已就可动手接入功能,--所有流程一目了然
- 面向制造商的实用电子产品(N的第一部分)
- bpmn.js+vue实现工作流设计器(左侧功能+右侧详情)
- python手绘教学_Python实现手绘图效果实例分享