Java后端编译与优化

这篇具有很好参考价值的文章主要介绍了Java后端编译与优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 如果我们将字节码看作是程序语言的一种中间表示形式,那编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码,它都可以视为整个编译过程的后端。

1 即时编译器

即时编译器是指运行时将热点代码编译成本地机器码,并以各种手段尽可能地进行代码优化的后端编译器。

1.1 解释器与编译器

1.1.1 解释器

将字节码解释成具体平台的机器码。

其主要作用是:

1)当程序需要迅速启动或执行时,解释器可以首先发挥作用,省去编译的时间。

2)节约内存。

3)作为编译器激进优化时后备的逃生门。

1.1.2 编译器

程序启动后,随着时间推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码,减少解释器的中间损耗,获得更高的执行效率。

HotSpot虚拟机中内置两个(或三个)即时编译器,其中两个分别为“客户端编译器”(Client Compiler)简称为C1编译器和“服务端编译器”(Server Compiler)简称为C2编译器,第三个是JDK10才出现的,长期目标是代替C2点Graal编译器。

1.1.3 分层编译

为了在程序启动响应速度和运行效率之间达到最佳平衡,HotSpot虚拟机在编译子系统中加入了分层编译的功能。在JDK 7 服务端模式虚拟机中作为默认编译策略被开启。

第0层。程序纯解释执行,并且解释器不开启性能监控功能。

第1层。使用客户端编译器将字节码编译为本地代码来运行,进行简单可靠的稳定优化,不开启性能监控功能。

第2层。仍使用客户端编译器执行,仅开启方法及回边次数统计等有限的性能监控功能。

第3层。仍使用客户端编译器执行,开启全部性能监控,除了第2层的统计信息外,还会收集如分支跳转、虚方法调用版本等全部等统计信息。

第4层。使用服务端编译器将字节码编译为本地代码,启用更多耗时更长的优化,还会根据性能监控信息进行一些不可靠的激进优化。

1.2 编译对象与触发条件

1.2.1 编译对象

会被即时编译器编译的目标是“热点代码”,主要由两类:1)被多次调用的方法。2)被多次执行的循环体。

1.2.2 触发条件

判断某段代码是不是热点代码,是否触发即时编译的这种行为称为“热点探测”。进行热点探测并不一定要知道方法具体被调用了多少次,目前主流的热点探测判定方式有两种:

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

该方法实现简单高效,还可以很容易地获取方法调用关系,缺点是很难精确地确认一个方法的热度,容易受到线程阻塞的影响。

2)基于计数器的热点探测。为每个方法(甚至是代码块)建立计数器,统计方法的执行次数。

该方法实现起来要麻烦些,但是统计结果相对来说更加精确严谨。

       方法调用计数器并不是方法被调用的绝对数,而是一个相对的执行频率。当超过一定时间限度,如果次数仍不足,那该方法的调用计数器就会被减少一半。这个过程被称为计数器热度的衰减,而这段时间被称为半衰周期。

1.3 编译过程

在默认条件下,虚拟机在编译器还未完成编译之前,都仍然将按照解释器方式继续执行代码,而编译动作则在后台的编译线程中进行。

服务端编译器和客户端编译器的编译过程是有所差别的。

1.3.1 客户端编译器

是一个相对简单快速的三段式编译器,主要的关注点在于局部性的优化,而放弃了许多耗时较长的全局优化手段。

Java后端编译与优化,JVM,java,linux,前端

图 客户端编译器大致的执行过程

第一阶段:将字节码完成一部分基础优化,如方法内联、常量传播等。然后构造成一种高级中间代码表示(HIR,即与目标机器指令集无关的中间表示)。HIR使用静态单分配(SSA)的形式来代表代码值。

第二阶段:在HIR上完成另一些优化,如空值检查消除、范围检查消除等。然后产生低级中间代码表示(LIR,即与目标机器指令集相关的中间表示)。

最后阶段:使用线性扫描算法在LIR上分配寄存器,并在LIR上做窥孔优化,然后产生机器代码。

1.3.2 服务端编译器

是专门面向服务端的典型应用场景,并为服务器性能配置针对性调整过的编译器,也是一个能容忍很高优化复杂度的高级编译器。

会执行大部份经典优化动作,还可能根据解释器或客户端编译器提供的性能监控信息,进行一些不稳定的预测性激进优化。

2 编译器优化技术

编译器的工作,难道不在于能否成功翻译出机器码,而在于输出代码优化质量的高低。

2.1 方法内联

最重要的优化技术之一。被称为优化之母,除了消除方法调用的成本之外,它更重要的意义是为其他优化手段建立良好的基础。

方法内联是把目标方法的代码原封不动地“复制”到发起调用到方法中。

public class MethodInline {
    static void method1() {
        System.out.println("method1");
    }

    static void method2() {
        System.out.println("method2");
        method1();
    }
}

上面代码经过方法内联后变为:

static void method2() {
    System.out.println("method2");
    System.out.println("method1");
}

在实际的内联过程,因为Java虚方法都必须在运行时进行方法接收者都多态选择,它们都可能存在多于一个版本的方法接收者。

2.1.1 类型继承关系分析(CHA)

为了解决虚方法的内联问题,Java虚拟机首先引入类型继承关系分析技术,范围为整个应用程序。用于确定目前已加载的类中,某个接口是否有多于一种的实现、某个类是否存在子类、某个子类是否覆盖了父类的某个虚方法等信息。

Java后端编译与优化,JVM,java,linux,前端

图 Java虚方法内联

2.2 逃逸分析

最前沿的优化技术之一。并不是直接优化代码的手段,而是为其他优化措施提供依据的分析技术。

基本原理:分析对象动态作用域,当一个对象在方法里被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,这种称为方法逃逸;甚至可能被外部线程访问到,称为线程逃逸。

如果证明一个对象不会逃逸到方法或线程之外,则可能为这个对象实例采取不同程度的优化,如:

  1. 栈上分配。如果确定一个对象不会逃逸出线程之外,那可以让这个对象在栈上分配内存(平常在堆中存储对象数据)。对象所占用到内存空间可以随栈帧出栈而销毁。栈上分配支持方法逃逸而不支持线程逃逸。
  2. 标量替换。一个数据已经无法再分解成更小的数据来表示了,称为标量,相反则称为聚合量。如果一个对象不会被方法外部访问,并且这个对象可被拆散,那么程序真正执行的时候将可以不去创建这个对象,而改用直接创建它的若干个被这个方法使用的成员变量来代替。
  3. 同步消除。线程同步本身是一个相对耗时的过程,如果一个变量不会逃逸出线程,那么这个变量的读写肯定就不会有竞争,对这个变量实施的同步措施就可以安全地消除掉。

 2.3 公共子表达式消除

语言无关的经典优化技术之一。含义是:如果一个表达式E之前已经被计算过,并且从先前计算到现在E中所有变量到值都没发生变化,那么E被称为公共子表达式。

int d = (c * b) * 12 + a + b * c。

优化过程为:

c * b 与 b * c是等价的,且这这段过程中,c与b的值没有发生变化。所以c * b 为公共表达式,设c * b = E,则经过优化的代码为:

int = E * 12 + a + E。

2.4 数组边界检查消除

语言相关的经典优化技术之一。Java每次数组元素的读写都带有隐含的条件判断操作(如检查下标是否合法)。

虚拟机会注册一个Segment Fault信号的异常处理器,这样,当下标合法时,对数组的访问不会有任何额外的开销,当不合法时,必须转到异常处理器中恢复中断并抛出NullPointException异常。此时速度远比上面的隐含条件判断操作慢得多。

所以假如下标经常不合法,这样的优化反而会让程序更慢。HotSpot会根据运行期收集到的性能监控信息自动选择合适的方案。文章来源地址https://www.toymoban.com/news/detail-556113.html

到了这里,关于Java后端编译与优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JVM执行引擎——为什么Java是半编译半解释语言

            起初设计者的初衷是将字节码文件翻译为机器语言的指令来执行即可,就诞生了解释器。但是采用一行行来解释的 效率比较低 ,JIT编译器会将编译后的机器码做一个缓存的操作,放在方法区的JIT代码缓存中,是否需要启用JIT编译器直接将字节码编译为机器码,则

    2024年02月15日
    浏览(35)
  • 前端传值,java后端接收

    var arr = [ 0, 1, 2]; var myJSON = JSON.stringify(arr); 此时myJSON字符串就是’[0,1,2]\\\',传给后台接受 前端 后端方法1(使用spring注解@RequestBody接收): 后端方法1的对象UserDto 后端方法2(使用JSON.parseArray()把前端 [{“loginAct”:111,“loginPwd”:1111},{“loginAct”:222,“loginPwd”:2222}] 数据转化为LI

    2024年02月13日
    浏览(26)
  • 49天精通Java,第34天,finalize、引用计数、JVM停止复制、JVM即时编译器

    在Java中,finalize()是一个Object类的方法,用于在对象被垃圾收集器回收之前执行一些清理操作。当一个对象成为垃圾时,它的finalize()方法会被自动调用。 finalize()方法的语法格式如下:

    2024年02月07日
    浏览(33)
  • java web(后端+前端) 学习路线记录---1.Java(更新中)

    资源:狂神说 1.注释、标识符、 (1) 建立空项目来建立java项目: (2) 单行注释://注释 (3) 多行注释:/* Djandjan / (4) 文档注释: / * */ 2标识符(类名,变量名,方法名) (5) (6) 标识符注意点: 2.数据类型 (1) 要求变量严格符合规范,所有变量先

    2024年02月20日
    浏览(27)
  • 多级菜单 树结构 排序 前端 后端 java

    目录 省流: 正文:  v1.0版  前端传的值: 后端代码: v2.0版 v3.0版 前端提交过来整个树即可。  给整个树进行sort。代码如下: 这个只是单纯排序,没有替换parentId。升级版本见正文。 排序完以后,结果如下: 一级节点的sort:1,2,3,4... 二级节点的sort:每个一级节点下的

    2024年02月06日
    浏览(26)
  • java和js实现前端加密后端解密,后端加密前端解密(Base64)

    目录 1.前端加密后端解密 2.后端加密前端解密 在前端和后端数据传输时,常常涉及到隐私数据的传输(例如用户名和密码),这时,我们就需要对隐私数据进行加密解密 1.前端加密后端解密         1.1 前端jquery实现         1.2后端 2.后端加密前端解密         2.1后端加密

    2024年02月16日
    浏览(39)
  • Java后端返回PDF预览给前端

    前端要预览服务器PDF 可直接将要blob流返回给前端 即可用浏览器自带pdf预览功能打开,现有两种方式 方式1 返回blob流给前端 代码如下        此时 前端解析可直接拿返回的文件流 例子如下 但有的时候 不想返回文件流 可把文件返回为base64 (注意 base64可能超长)此时代码修

    2024年02月08日
    浏览(40)
  • 后端java 如何返回给前端 JSON数据

    在上述代码中,@ResponseBody注解用于将Java List对象转换为JSON格式的数据,并返回给前端。Spring会自动将List对象转换为JSON格式的数组,其中每个元素都是一个JSON对象。在本例中,每个JSON对象都包含一个name属性和一个age属性。 Regenerate

    2024年02月15日
    浏览(27)
  • 微信小程序练手实战:前端+后端(Java)

    现在微信小程序越来越火了,相信不少人都通过各种途径学习过微信小程序或者尝试开发,作者就是曾经由于兴趣了解开发过微信小程序,最终自己的毕业设计也是开发一个微信小程序。所以现在用这篇博客记录我之前开发的一些经验和一些心得吧。 springboot后端架构构建 小

    2024年02月10日
    浏览(29)
  • TOMCAT部署及优化(Tomcat配置文件参数优化,Java虚拟机(JVM)调优)

    TOMCAT tomcat :是一个开放源代码的web应用服务器,基于java代码开发的。也可以理解为tomacat就是处理动态请求和基于java代码的页面开发。可以在html当中写入java代码,tomcat可以解析html页面当中的java,执行动态请求,动态页面。 tomcat是机制存在一些问题,如果不对tomcat进行优化

    2024年02月13日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包