专栏的前几篇文章了解了JVM的内存模型,GC调优的思路,让我们对于Java底层有了一定的了解,那么采用这种思路去提高JVM的性能,减少JVM额外消耗的同时,JVM究竟做了哪些工作,使我们的Java代码得到了优化呢?

今天主要将关于Java的生命周期和JVM运行时候的优化方法进行一下描述,让大家知道JVM优化时,究竟在Java运行中,JVM究竟做了什么???

简述

Java程序运行起来之后,JVM对代码的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。运行时优化主要是解释执行和动态编译通用的一些机制,比如说:锁机制(如偏斜锁)、内存分配机制(如TLAB)等。除此之外,还有一些专门用于优化解释执行效率的,比如说模版解释器、内联缓存( inline cache,用于优化虚方法调用的动态绑定)。

之前的专栏中讲到Java程序在JVM中执行的时候,首先会以方法为module转化为JVM可以识别的数据结构,直接运行在底层硬件上。采用的优化方式主要如下:

  1. 方法内联
  2. 逃逸分析
  3. 基于程序运行profile的投机性优化

主要来解释一下第三条:比如有一条instanceof指令,在编译之前的执行过程中,测试对象的类一直是同一个,那么即时编译器可以假设编译之后的执行过程中还会是这一个类,并且根据这个类直接返回instanceof的结果。如果出现了其他类,那么就抛弃这段编译后的机器码,并且切换回解释执行。

JVM的优化方式仅仅作用在运行应用代码的时候,如果应用代码本身阻塞了,比如说并发时等待另一线程的结果,这就不再JVM的优化范畴。

今天专栏侧重于:

  • Java的生命周期
  • JIT及其调优

知识扩展

1、Java生命周期

示意图如下:

前面讲到Java在编译的时候,将代码转换为字节码,这样屏蔽了不同硬件的差异,然后由JVM负责完成从字节码到机器码的转化。

在编译期间会进行少量类似常量折叠之类的优化,只要利用反编译工具就可以直接查看细节。

javac优化与JVM内部优化存在关联,毕竟它负责了字节码的生成。

今天的重点是JVM运行时的优化,通常情况JIT和解释器一起作用,参考下图:

JVM会动态决定哪些方法被编译,哪些方法被执行,即使是已经编译过的代码,也可能不再是热点,会被移除。

JVM内存模型中存在Java虚拟机栈,对应一个线程,且线程本身拥有不断由JVM管理的入栈,出栈的栈帧,控制方法的进入与出去。而优化的细节,就可以从GC调优思路入手去回顾,通过不断的编译,检验方法的热点程度,也就是我们之前的新生代逐步走向老年代的过程,这也就对应了,没有价值的方法会被Code Cache清除这一过程了。

在解释器和编译器中,也会进行一些通用优化:

  1. 锁优化
  2. 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代码时都做了什么?相关推荐

  1. asp java 变量_ASP_用stack变量优化Java代码,  java程序包含了大量的对象 - phpStudy...

    用stack变量优化Java代码 java程序包含了大量的对象,我们需要了解它们是从哪里被访问的,变量存储于何处对程序的性能有显著的影响--尤其是某些需要被频繁访问的变量. 我们写一个Java类,在其 ...

  2. java+set+split_阿里资深工程师教你如何优化 Java 代码!

    原标题:阿里资深工程师教你如何优化 Java 代码! 作者 | 王超 责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见 ...

  3. 写java代码时的注意事项_从方法返回Java 8的可选项时的注意事项

    写java代码时的注意事项 Java 8引入的Optional类一直是该语言版本引入的最具争议的功能之一. 尽管我喜欢这个新的Java类的东西比不喜欢的东西多,但在Java方法中将其用作return类 ...

  4. 运行java提示找不到符号_运行java代码时出现找不到符号错误怎么解决

    运行java代码时出现找不到符号错误怎么解决 发布时间:2020-06-23 11:37:00 来源:亿速云 阅读:113 作者:Leah 运行java代码时出现找不到符号错误怎么解决?针对这个问题, ...

  5. 运行Java代码时,遇到java.io.IOException: parseAlgParameters failed: PBE AlgorithmParameters not available

    运行Java代码时,遇到parseAlgParameters failed: PBE AlgorithmParameters not available java.io.IOException: pa ...

  6. 提升效率:优化Java代码的35个小技巧

    每天早晨,干货准时奉上! 本文作者:萌小Q 来源: www.cnblogs.com/Qian123/p/6046096.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方 ...

  7. java代码_阿里资深工程师教你如何优化 Java 代码!

    作者 | 王超责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见道无终穷,愈探愈深,必使精白无一毫不彻方可. 代码中的& ...

  8. 阿里资深工程师教你如何优化 Java 代码!

    作者 | 王超 责编 | 伍杏玲 明代王阳明先生在<传习录>谈为学之道时说: 私欲日生,如地上尘,一日不扫,便又有一层.着实用功,便见道无终穷,愈探愈深,必使精白无一毫不彻方可. 代码中的 ...

  9. IntelliJ IDEA 编译Java代码时,中文乱码问题

    有很多文章介绍了这些方法,都一般都是只有前两项,或是只有第三项.这里全放上吧,做个记录. 在导入别人的项目或是自己以前的项目时,在 Build Project 时,会出现因为中文注释的乱码,所导致的编 ...

最新文章

  1. javascript中五句话
  2. PyQt5 笔记4 -- 多线程
  3. mac 10.11 安装mysql5.7.10压缩版
  4. otb100matlab,ECO for tracking 在 OTB100 基准测试和 VOT2016 数据集中的实验结果
  5. (王道408考研数据结构)第五章树-第四节4:红黑树基本概念及操作
  6. 安卓平台下的即时通讯
  7. STM32使用大彩串口屏程序框架使用总结
  8. YOLO系列目标检测数据集大全
  9. grpc系列1-K8S集群,VIP,grpc._channel._InactiveRpcError connection reset by peer解决方案 Paddleserving服务化部署
  10. css样式中的vw什么意思,css vw是什么单位
  11. 三颗种子开发系统源码
  12. 2020牛客寒假算法基础集训营3 B 牛牛的DRB迷宫II二进制详解
  13. 二元置信椭圆r语言_R语言 第4章 初级绘图(6)
  14. .Net MAUI 安卓状态栏透明、半透明、全屏
  15. ssh 免账号密码登录
  16. 覆盖式理解Android 消息处理机制(带源码解析)
  17. 行云管家V4.9正式发布:监控全面提升,首页、主机详情大幅优化,新增大量实用功能.md...
  18. 操作系统-Linux内核系列
  19. 城市公交查询系统c语言,城市公交查询系统城市公查询系统.doc
  20. 泰拉瑞亚安装、运行教程

热门文章

  1. 杭电和苏大计算机考研,江苏省各高校“排行榜”出炉,江苏大学10名开外,南大当属第一!...
  2. 内置Prisemi保护IC P14C1N,安克、真我、万魔、红米等全新产品TWS耳机上应用,现推荐安克举例。
  3. vivo2020届春季校园招聘手机屏幕解锁模式
  4. (转)Android闪屏问题解决思路
  5. Sentinel(四)限流算法-令牌桶算法
  6. mapbox图形绘画以及polygon信息提取
  7. 2021年PC电脑网站接入微信登陆支付精讲--1小时自已就可动手接入功能,--所有流程一目了然
  8. 面向制造商的实用电子产品(N的第一部分)
  9. bpmn.js+vue实现工作流设计器(左侧功能+右侧详情)
  10. python手绘教学_Python实现手绘图效果实例分享