龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

Java虚拟机JVM性能优化(二):编译器

时间:2014-09-20 11:11来源:网络整理 作者:网络 点击:
分享到:
这篇文章主要介绍了Java虚拟机JVM性能优化(二):编译器,本文先是讲解了不同种类的编译器,并对客户端编译,服务器端编译器和多层编译的运行性能进行了对比,然后给出了几种常见的

本文将是JVM 性能优化系列的第二篇文章(第一篇:传送门),Java 编译器将是本文讨论的核心内容。

本文中,作者(Eva Andreasson)首先介绍了不同种类的编译器,并对客户端编译,服务器端编译器和多层编译的运行性能进行了对比。然后,在文章的最后介绍了几种常见的JVM优化方法,如死代码消除,代码嵌入以及循环体优化。

Java最引以为豪的特性“平台独立性”正是源于Java编译器。软件开发人员尽其所能写出最好的java应用程序,紧接着后台运行的编译器产生高效的基于目标平台的可执行代码。不同的编译器适用于不同的应用需求,因而也就产生不同的优化结果。因此,如果你能更好的理解编译器的工作原理、了解更多种类的编译器,那么你就能更好的优化你的Java程序。

本篇文章突出强调和解释了各种Java虚拟机编译器之间的不同。同时,我也会探讨一些及时编译器(JIT)常用的优化方案。

什么是编译器?

简单来说,编译器就是以某种编程语言程序作为输入,然后以另一种可执行语言程序作为输出。Javac是最常见的一种编译器。它存在于所有的JDK里面。Javac 以java代码作为输出,将其转换成JVM可执行的代码—字节码。这些字节码存储在以.class结尾的文件中,并在java程序启动时装载到java运行时环境。

字节码并不能直接被CPU读取,它还需要被翻译成当前平台所能理解的机器指令语言。JVM中还有另一个编译器负责将字节码翻译成目标平台可执行的指令。一些JVM编译器需要经过几个等级的字节码代码阶段。例如,一个编译器在将字节码翻译成机器指令之前可能还需要经历几种不同形式的中间阶段。

从平台不可知论的角度出发,我们希望我们的代码能够尽可能的与平台无关。

为了达到这个目的,我们在最后一个等级的翻译—从最低的字节码表示到真正的机器代码—才真正将可执行代码与一个特定平台的体系结构绑定。从最高的等级来划分,我们可以将编译器分为静态编译器和动态编译器。 我们可以根据我们的目标执行环境、我们渴望的优化结果、以及我们需要满足的资源限制条件来选择合适的编译器。在上一篇文章中我们简单的讨论了一下静态编译器和动态编译器,在接下来的部分我们将更加深入的解释它们。

静态编译 VS 动态编译

我们前面提到的javac就是一个静态编译的例子。对于静态编译器,输入代码被解释一次,输出即为程序将来被执行的形式。除非你更新源代码并(通过编译器)重新编译,否则程序的执行结果将永远不会改变:这是因为输入是一个静态的输入并且编译器是一个静态的编译器。

通过静态编译,下面的程序:

复制代码 代码如下:

staticint add7(int x ){      return x+7;}

将会转换成类似下面的字节码:

复制代码 代码如下:

iload0 bipush 7 iadd ireturn

动态编译器动态的将一种语言编译成另外一种语言,所谓动态的是指在程序运行的时候进行编译—边运行边编译!动态编译和优化的好处就是可以处理应用程序加载时的一些变化。Java 运行时常常运行在不可预知甚至变化的环境上,因此动态编译非常适用于Java 运行时。大部分的JVM 使用动态编译器,如JIT编译器。值得注意的是,动态编译和代码优化需要使用一些额外的数据结构、线程以及CPU资源。越高级的优化器或字节码上下文分析器,消耗越多的资源。但是这些花销相对于显著的性能提升来说是微不足道的。

JVM种类以及Java的平台独立性

所有JVM的实现都有一个共同的特点就是将字节码编译成机器指令。一些JVM在加载应用程序时对代码进行解释,并通过性能计数器来找出“热”代码;另一些JVM则通过编译来实现。编译的主要问题是集中需要大量的资源,但是它也能带来更好的性能优化。

如果你是一个java新手,JVM的错综复杂肯定会搞得你晕头转向。但好消息是你并不需要将它搞得特别清楚!JVM将管理代码的编译和优化,你并不需要为机器指令以及采取什么样的方式写代码才能最佳的匹配程序运行平台的体系结构而操心。

从java字节码到可执行

精彩图集

赞助商链接