JRockit读书笔记I — Java代码的高效执行

《Oracle JRockit: The Definitive Guide》一书是由Oracle JRockit的两位资深开发人员写的,其中的Marcus Hirt更是JRockit Mission Control的leader,这本书详细的对Oracle JRockit进行了介绍,最突出的特点非常系统化的介绍了一个JVM通常是如何实现的,而JRockit这样一个极为优秀的JVM又是做了哪些优化,为什么做这些优化,这本书对于对JVM感兴趣的同学而言应该是必读的一本书,其实即使对于JVM兴趣不强的同学,里面的优化思路的介绍也是值得学习,本系列的blog主要是总结看这本书得到的一些收获,由于书中知识量巨大,因此得分成多篇blog来总结了。

书的第二章为:Adaptive Code Generation,在这章中作者向我们讲解了一个优秀的JVM是如何来实现代码的高效执行的,感兴趣的同学其实可以在不看下面blog内容之前,先考虑下如果是你做的话,你会怎么做来实现Java代码的高效执行呢,然后再对比下这章的内容,我想你能学到很多的,:)

用过Java的同学都知道,Java是通过javac将Java源码编译为class文件,然后通过ClassLoader装载此class文件,之后就可执行此class了,要最高效的执行这个class,最好的方法莫过于class文件直接就是机器码,这样直接执行就可以了,但Java是跨平台的,因此class文件就不能是机器码了。

由于class文件不是直接的机器码,要执行它最简单的方法就是采用纯粹的解释方式,解释方式由于每次都得将class文件中的指令翻译为对应的机器环境的指令,效率是很低的。

为了能更高效的执行,同时又保持跨平台的特性,另外一个方法就是在执行class时再将其翻译为对应的机器码,这个方法是比较靠谱的,因此无论是 Hotspot、还是JRockit,都采用了这种方式,也就是大家熟知的JIT(Just In Time) Compiler。

OK,既然觉得在装载class后翻译成机器码去执行可以比较高效,那这个时候又会出现两种状况,是执行class的时候就立刻翻译成机器码,还是先用解释模式执行,然后到一定时机再翻译成机器码呢,之所以出现这两种状况,原因在于将class翻译为机器码是需要消耗时间的,因此如果执行class 的时候就立刻翻译成机器码的话,也就会导致Java程序启动速度会比较慢,JRockit是这么认为的,JRockit的服务对象是server级应用,这类应用的特点是没那么在乎启动速度,而更在乎的是执行时的高效,而且如果执行的时候就立刻翻译成机器码的话,就意味着压根不需要实现解释器,因此 JRockit采取的方法是在执行class时直接编译为机器码,而Hotspot由于需要同时支持client和server应用,对于client应用而言,启动速度非常重要,因此Hotspot采用的是先解释执行,到了一定时机后再翻译成机器码。

如果认为就这样就完成了Java代码的执行的实现,那就太小看JVM了,由于JVM能够知道代码运行的全部状况,自然还可以做出更多更出色的提升代码执行速度的优化,例如标量替换、更好的inline等,后面再来细说,因此这样就出现了一个状况,什么时候对哪些代码来做这些更猛的优化呢。

真正值得做更猛的优化的代码自然是所谓的”热点”代码,如何来发现哪些代码是热点代码呢,通常有三种方法:
1、方法调用计数器
方法调用计数器是常见的方式,hotspot采用的即为这种,这种方式不好的地方就在于计数器本身经常是cpu cache misses的,因此稍微会有点影响性能。
2、对线程进行采样
可采用软件或硬件方式来实现,软件方式实现不好的地方在于采样的时候需要暂停线程,好处是因为是采样,不需要对所有方法进行计数,硬件方式自然是最好的,但不是所有的硬件都支持的,支持的硬件中最典型的是intel IA-64的CPU。

在有了发现热点代码的方法后,接下来需要做的就是更猛的优化,有很多种,例如Java的代码中,通常会是接口方式的调用,但因为是接口方式的调用,所以其实默认情况下是不好做inline处理的,但JVM为了更高效的执行代码,如发现这代码为热点代码,那么就会做一些激进的优化,例如会假设这个接口只有一个实现,然后就可以直接将此实现对应的代码inline进来了(至于为什么inline后效率更高,这个请参考编译原理之类的书),这些激进优化同样适合于if、抛异常这些状况,当然,当激进优化的条件失效时,就会逆优化回到之前基本编译的代码。
而其他的更猛的优化还包括根据线程执行路径进行逃逸分析等,后面再专门写一篇blog来讲解下一些翻译为机器码的优化吧,其实大多都是编译原理的一些东西。

书中在介绍JRockit如何实现自己的JIT Compiler时,提到了Bytecode混淆以及bytecode优化,JRockit的态度是bytecode混淆时将name进行混淆是靠谱的,但如果对control flow进行混淆,就不太好了,因为这有可能会导致jit compile时的有些优化也做不了了,而bytecode优化,JRockit的态度是应该避免,因为没什么太大的意义,更主要的优化还是得靠jit compiler。

JRockit的JIT Compiler的实现和Hotspot另外一个很大的不同在于JRockit并未采用on-stack replacement,据JRockit的研究,这个没有太大必要,当然,对于编写benchmark代码时则要注意这个不同。

JIT Compiler在compile时还需要考虑的几个重点问题:
1、为GC提供必要的信息;
2、为查错提供必要的信息,例如代码的行数、变量名等;

从这章的内容可以看到,JRockit为了能够让Java代码能够高效的执行,是做出了非常多的努力的,也可以看到很多JRockit与Hotspot不同的地方,甚至可以看出Java代码的执行比C代码的执行高效都是有可能的,:)。

本文来源于"阿里中间件团队播客",原文发表时间" 2010-12-16"

时间: 2024-07-28 13:16:16

JRockit读书笔记I — Java代码的高效执行的相关文章

让Java代码更高效_java

本文简单介绍一下在写代码过程中用到的一些让JAVA代码更高效的技巧. 1,将一些系统资源放在池中,如数据库连接,线程等.在standalone的应用中,数据库连接池可以使用一些开源的连接池实现,如C3P0,proxool和DBCP等,在运行在容器中的应用这可以使用服务器提供的DataSource.线程池可以使用JDK本身就提供的java.util.concurrent.ExecutorService. import java.util.concurrent.Executors; import j

JVM学习笔记(二)------Java代码编译和执行的整个过程

Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: ● Java源码编译机制 ● 类加载机制 ● 类执行机制 Java源码编译机制 Java 源码编译由以下三个过程组成: ● 分析和输入到符号表 ● 注解处理 ● 语义分析和生成class文件 流程图如下所示: 最后生成的class文件由以下部分组成: ● 结构信息.包括class文件格式版本号及各部分的数量与大

JVM学习笔记(二)------Java代码编译和执行的整个过程【转】

转自:http://blog.csdn.net/cutesource/article/details/5904542 版权声明:本文为博主原创文章,未经博主允许不得转载. Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示:   Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码编译机制 类加载机制 类执行机制 Java源码编译机制 Java 源码编译由以下三个过程组成: 分析和输入到符号表 注解处理

怎样在java代码中调用执行shell脚本呀

问题描述 遇到个问题   在本地压缩服务器上的xml文件 我就想编写shell教本 脚本内容是链接服务器 找到待压缩文件 压缩文件  说实话 我不知道这样是否可行  试试  但我不知道怎样在java代码中 调用执行shell脚本  谁能指点指点  求教...  问题补充:首先谢谢各位朋友的回答  在补充个小问题 <br />能在调用shell脚本时 同时给shell脚本传参数吗  不止一个 能这样写吗     <br />Runtime.getRuntime().exec(&quo

《淘宝技术这十年》读书笔记 (二).Java时代的脱胎换骨和坚若磐石

        马云说过"一个好的东西往往是是说不清楚的",姑且不论这句话的对与错.但我真的很佩服<淘宝技术这十年>这本书的作者子柳,能够通过淘宝的一些故事,按照时间顺序和IT发展的各种技术描述清楚,而且过程中读起来非常有意思.         该读书笔记中参杂了很多原文的知识,因为我实在无法割舍,都挺有意思的:同时记录一些有用的知识,通过这本书能介绍些学过的知识或面试中可能出现的题目及作者所思,文章还是非常有趣的,希望对大家有所帮助! 一. Java时代 脱胎换骨    

《淘宝技术这十年》读书笔记 (三). 创造技术TFS和Tair

        前面两篇文章介绍了淘宝的发展历程和Java时代的变迁:             <淘宝技术这十年>读书笔记 (一).淘宝网技术简介及来源             <淘宝技术这十年>读书笔记 (二).Java时代的脱胎换骨和坚若磐石         马云说过"创新不是为了与对手竞争,而是跟明天竞争",所以这篇文章讲述淘宝的创新技术TFS和Tair及创新的产品.         该篇文章不仅仅对在读大学生非常有所帮助,因为你能从文章中看到很多你需要学

《淘宝技术这十年》读书笔记 (四). 分布式时代和中间件

        前面两篇文章介绍了淘宝的发展历程.Java时代的变迁和淘宝开始创新技术:            <淘宝技术这十年>读书笔记 (一).淘宝网技术简介及来源            <淘宝技术这十年>读书笔记 (二).Java时代的脱胎换骨和坚若磐石            <淘宝技术这十年>读书笔记 (三).创造技术TFS和Tair        这篇文章主要讲述分布式时代和中间件相关知识,包括服务化.HSF.Notify和TDDL.同时里面有我们经常遇见的编

java代码的在线运行,对其内存限制,时间检测等问题[ga]

问题描述 java代码的在线运行,对其内存限制,时间检测等问题[ga] 基本需求类似[java在线代码编译运行],多个客户都可以各自通过web浏览器输入java代码, 然后点击执行java代码,输出结果. 我是通过(Class thisClass = Class.forName(className,true,ClassLoader.getSystemClassLoader()); 来实现的) 目前比较担心某个用户输入的java代码可能是个死循环(如:while(true){xxxx}), 或者高

javaweb-java代码中没法执行首页、上一页、下一页操作

问题描述 java代码中没法执行首页.上一页.下一页操作 emp_list.jsp调用split_page_plugin.jsp实现对数据库表的分页查询和模糊查询操作,但是最后出来的效果无法实现分页查询中的首页.上一页.下一页操作操作,相应按钮也不亮,如图,我用的是mysql数据库,请高手帮我调试一下,非常感谢,相应代码如下: emp_list.jsp <%@ page contentType="text/html" pageEncoding="GBK"%&g