JVM性能调优实战之jvm优化和tomcat优化

http://www.importnew.com/2009.html 作为JVM性能优化系列文章的第2篇 , 本文将着重介绍Java编译器 , 此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化 , Part 1″中对JVM的介绍) 。Eva Andreasson将对不同种类的编译器做介绍 , 并比较客户端
http://www.importnew.com/2009.html


作为JVM性能优化系列文章的第2篇 , 本文将着重介绍Java编译器 , 此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化 , Part 1″中对JVM的介绍) 。Eva Andreasson将对不同种类的编译器做介绍 , 并比较客户端、服务器端和层次编译产生的编译结果在性能上的区别 , 此外将对通用的JVM优化做介绍 , 包括死代码剔除、内联以及循环优化 。
Java编译器存在是Java编程语言能独立于平台的根本原因 。软件开发者可以尽全力编写程序 , 然后由Java编译器将源代码编译为针对于特定平台的高效、可运行的代码 。不同类型的编译器适合于不同应用程序的需求 , 使编译结果可以满足期望的性能要求 。对编译器基本原理了解得越多 , 在优化Java应用程序性能时就越能得心应手 。
什么是编译器
简单来说 , 编译器就是将一种编程语言作为输入 , 输出另一种可执行语言的工具 。大家都熟悉的javac就是一个编译器 , 所有标准版的JDK中都带有这个工具 。javac以Java源代码作为输入 , 将其翻译为可由JVM执行的字节码 。翻译后的字节码存储在.class文件中 , 在启动Java进程的时候 , 被载入到Java运行时中 。
标准CPU并不能识别字节码 , 它需要被转换为当前平台所能理解的本地指令 。在JVM中 , 有专门的组件负责将字节码编译为平台相关指令 , 实际上 , 这也是一种编译器 。有些JVM编译器可以处理多层级的编译工作 , 例如 , 编译器在最终将字节码转换为平台相关指令前 , 会为相关的字节码建立多层级的中间表示(intermediate representation) 。
字节码与JVM
如果你想了解更多有关字节码与JVM的信息 , 请阅读 “Bytecode basics”(Bill Venners, JavaWorld)
以平台未知的角度看 , 我们希望尽可能的保持平台独立性 , 因此 , 最后一级的编译 , 也就是从最低级表示到实际机器码的转换 , 是与具体平台的处理器架构息息相关的 。在最高级的表示上 , 会因使用静态编译器还是动态编译器而有所区别 。在这里 , 我们可以选择应用程序所以来的可执行环境 , 期望达到的性能要求 , 以及我们所面临的资源限制 。在本系列的第1篇文章的静态编译器与动态编译器一节中 , 已经对此有过简要介绍 。我将在本文的后续章节中详细介绍这部分内容 。
静态编译器与动态编译器
前文提到的javac就是使用静态编译器的例子 。静态编译器解释输入的源代码 , 并输出程序运行时所需的可执行文件 。如果你修改了源代码 , 那么就需要使用编译器来重新编译代码 , 否则输出的可执行性文件不会发生变化;这是因为静态编译器的输入是静态的普通文件 。
使用静态编译器时 , 下面的Java代码
static int add7( int x ) { return x+7;}
会生成类似如下的字节码:
iload0bipush 7iaddireturn
动态编译器会动态的将一种编程语言编译为另一种 , 即在程序运行时执行编译工作 。动态编译与优化使运行时可以根据当前应用程序的负载情况而做出相应的调整 。动态编译器非常适合用于Java运行时中 , 因为Java运行时通常运行在无法预测而又会随着运行而有所变动的环境中 。大部分JVM都会使用诸如Just-In-Time编译器的动态编译器 。这里面需要注意的是 , 大部分动态编译器和代码优化有时需要使用额外的数据结构、线程和CPU资源 。要做的优化或字节码上下文分析越高级 , 编译过程所消耗的资源就越多 。在大多数运行环境中 , 相比于经过动态编译和代码优化所获得的性能提升 , 这些损耗微不足道 。