JAVA虚拟机性能参数调优指导书.docx
《JAVA虚拟机性能参数调优指导书.docx》由会员分享,可在线阅读,更多相关《JAVA虚拟机性能参数调优指导书.docx(20页珍藏版)》请在三一办公上搜索。
1、JAVA虚拟机性能参数调优指导书Java虚拟机性能参数调优指导书 (仅供内部使用) 目 录 1 概述 . 5 2 JAVA虚拟机运行机制概览 . 5 2.1 运行时分析 . 5 2.2 垃圾收集和线程同步 . 7 3 JAVA虚拟机参数分类说明 . 8 3.1 Java虚拟机标准参数. 8 3.2 Java虚拟机扩展参数. 10 4 JAVA应用性能测试调优经验总结 . 13 4.1 GC调优参数的使用 . 13 4.2 JIT调优参数的使用 . 14 4.3 Java线程调优参数的使用 . 14 5 结束语 . 15 6 参考文献 . 15 表目录 表1 JVM 标准参数集 . 10 表2
2、JVM 扩展参数集 . 10 表3 JVM GC/Hotspot相关参数集 . 12 表4 JVM 性能统计参数集 . 13 错误!未找到引用源。 关键词:Java、垃圾收集、虚拟机、即时编译 摘 要: 随着JAVA在应用系统级的项目开发中的使用越来越广泛,虚拟机、垃圾收集、热点编译、J2EE等新技术层出不穷,JAVA作为系统级开发的一个选择的优势也越来越明显,在此同时其不能完全编译、垃圾收集等与生俱有的特征也使得JAVA备受争议的“慢”得到更多的关注。本文通过对JAVA虚拟机的运行机理的分析,以及JAVA虚拟机参数使用说明等描述,试图使读者能够更好的运行他的基于JAVA的应用系统,以最小的代
3、价换取最大的收益。 缩略语清单: 缩略语 JAVA JVM GC HotSpot JIT 英文全名 Java Virtual Machine Garbage Collection Just-In-Time 中文解释 SUN公司发明的一种语言 JAVA虚拟机 垃圾收集 Java虚拟机内部的一种热点编译技术 即时编译技术 1 概述 Java在大行其道的同时也在为自己与生俱来的缺陷不断的努力着,我们有理由相信Java的开发设计者们真是一群天才。构成Java技术的基石就是JVM的虚拟机技术,这时的Java已经不再是一门简单的语言,而是语言、开发包JDK与虚拟机的完美结合,而这里面的虚拟机则是融合了编译
4、技术、CPU技术的Java存在的基础所在。既然那么多的优秀的人为提升虚拟机性能做了那么多的工作,我们有什么理由不去充分利用这些宝贵的资源呢?本文就是试图从原理分析到参数应用上来帮助读者更大的发挥Java虚拟机的性能极限,使这样一个优秀的产品更好地为我们服务。 2 JAVA虚拟机运行机制概览 2.1 运行时分析 首先让我们来看看所谓的Java虚拟机在运行起来后是什么样子的,从外面来看一个Java虚拟机的运行实例就是一个运行着的Java进程,Java进程在启动过程中做了如下工作,一、根据环境变量的设置或者Java进程的命令行参数将Java Class字节码加载到内存中,这样的Java字节码是Jav
5、a虚拟机所能够识别的虚拟机指令的集合,Java虚拟机在解释执行字节指令的同时,根据某些代码的使用频率,将其中一部分字节码翻译成机器能够识别的二进制指令保存在内存中,在以后对这部分代码的调用,则由Java虚拟机的代码控制CPU直接执行内存中的这部分二进制指令,这个就是Java虚拟机的热点编译技术。而在早期的Java虚拟机实现中是采用全部字节程序解释执行的方式,后来发展了Java静态编译技术,这种技术是在Java程序编译成字节码后,由一个本地编译器将这些字节码编译成二进制可执行文件,这种编译技术不利于程序的移植。再后来发展的Java的动态编译技术,这时的编译过程是在Java装载字节码文件时进行的,
6、而此时的问题是Java在启动时需要花费很长的时间来编译这些字节码。直到最后流行的Hotspot技术的出现,此时编译仅仅运行于少部分代码。按照80/20的原则,程序的百分之80的时间仅仅运行其百分之20的代码,这样一个能够平衡启动时间、移植性的中间方法解决了人们的大部分问题。 之后,让我们看看Java虚拟机的内部体系结构,从下面的体系机构图来看,Java的Class字节码文件经由类加载子系统加载到内存中时,虚拟机根据文件内容将类的方法和数据加载到称为方法区的地方,堆是用来为运行时类实例提供存放场所的地方,这样的堆也称之为对象堆空间。而Java栈和PC计数器则是为了Java线程而设计的,每一个Ja
7、va线程一旦创建,它都将得到一个属于他自己的PC计数器以及一个线程栈,在新版本Java Hotspot VM中是没有本地方法栈和线程栈之分的,只有一个线程栈的模块。这样每个线程的运行都是在属于自己栈空间内的,而所有的线程则共享着一个堆空间。当然在线程实现上不同的Java虚拟机的内部实现可能各有不同,有的自是直接将Java线程和操作系统内核线程绑定起来的,在虚拟机进程内部创建一个Java线程虚拟机就会请求操作系统为该一个进程创建一个内核线程,将线程之间的调度交给了操作系统内核来完成。而在早期的Java虚拟机一些实现中,Java线程对于操作系统来说是不可见,而是由应用层来完成线程调度,对于操作系统
8、来说仅仅是一个单线程的进程。 图1 Java虚拟机的内部体系结构 Java虚拟机在运行时,由主线程开始解释执行类文件中的指令,主线程在自己的线程栈中存放临时变量、参数变量等,一旦碰到生成新对象的new操作时,就会在堆空间内申请一块内存存放该类对象,而一旦程序从一个方法中退出后,虚拟机程序并不会立即释放Heap空间内的这块内存,这就是与C/C+程序所不同的地方,因为C/C+程序被加载程序的操作系统调用装载到内存中之后,程序的内存是由操作系统为之分配的4G的虚拟内存空间,而堆空间的使用也是由程序的内存分配子系统来完成的,而这个子系统仅仅是向程序员提供了申请/释放内存的调用接口,查看C/C+编译器生
9、成的汇编代码你会发现,如果你在一个函数中申请了一块内存,而没有在函数退出的地方没有释放的话,这块内存则会永远放在堆中,而对于你在函数中生明的类变量对象来说,这个类对象的内存是在程序栈空间中分配的,一旦这个函数释放则对象空间自动释放,这样的内存泄漏正是Java竭力避免的,Java从发明之初就是考虑着如何将大部分应用程序员从繁重的内存管理工作中解脱出来,而由Java虚拟机使用称之为GC垃圾收集的模块来完成内存空间的管理。Java虚拟机在启动时会根据-Xms的参数值向操作系统一次性申请一块内存空间作为自己的堆,而随着后续程序的运行中内存需求的增加,则再向操作系统申请更多的内存加到自己的堆空间中。这个
10、堆空间的最大值就是由-Xms指定的。一旦Java虚拟机发现应用程序申请的内存超过了堆内存的最大空间的话,Java就会抛出一个超出堆空间的异常。而当虚拟机在启动时如果申请不到足够的内存的话,则同样会抛出一个异常,启动失败。所有这些工作都是由Java虚拟机的内存管理模块来完成的,而Java的内存管理功能中最俱特色和重要的垃圾收集功能GC则是按照下面机制运行的。 2.2 垃圾收集和线程同步 Java的垃圾收集器就像一个兢兢业业的仓库保管员,他管理着虚拟机堆空间的清扫工作,接着上面描述的,一旦一个函数退出了它的栈,在该函数内声明的一个Java对象则会留在Java堆空间内,那么垃圾收集器会不会立即将这个
11、对象的空间释放呢?答案是否定的,垃圾收集器只有在当堆空间占用到了一定程度时,或者程序比较空闲时才释放那些不再使用的对象空间。如果此时程序堆空间的使用不是很大,而程序又比较忙的话,则垃圾收集器就不会运行。当然程序员也可以通过在程序中调用JDK接口来申请虚拟机主动执行垃圾收集器。而垃圾收集器的工作和C/C+语言中明确的释放对象比起来有一个潜在的缺点,那就是,在垃圾收集的Java应用中程序员对于安排CPU时间进行内存回收缺乏控制,想要精确地预测出何时进行垃圾收集、收集需要多长时间,基本上是不可能的。在早期的垃圾收集策略中,对象引用计数收集算法是最先被采用的,堆中的每个对象都有一个引用计数,当这个对象
12、被赋值给一个变量,则该引用计数器加1,当一个对象超过了生命期或者被重新赋值的话,对象的引用减一,任何引用计数为0的对象都可以被当作垃圾收集。这样的算法一个固有的缺陷就是无法处理循环应用的情况,而且计数的增减也会带来开销。现代的Java虚拟机的实现中采用了压缩收集算法、拷贝收集算法、按代收集算法等,按代收集的算法是为了解决GC在回收对象空间的优先顺序的问题,在按代收集的算法中,GC总是优先回收那些短暂年幼的对象,而非一些寿命较长的对象。JVM堆被划分成多个小的区域子堆,每个子堆分别为不同“代”的对象服务,如果一个年幼的对象经历过好几次垃圾收集后都没有别收集掉,则它就变成一个年老的对象,会被转移到
13、另一个存放寿命更长的对象的堆中。一切的改进就是本着让垃圾收集更快、更高效的目标进行的。在Java的语法里面,一个对象可以拥有终结方法,该方法是在垃圾收集器释放对象前必须执行的,程序员可以通过使用该方法来实现一些应用级清扫工作。 可以在编程语言级支持多线程是Java语言的一大优势,这种支持主要集中在同步上。对于编译型语言C/C+来说,在语言级是没有多线程的概念的,程序员只能通过调用操作系统API来实现多线程应用。而在Java中线程的支持是通过一些预先定义好的关键字来实现,而且JDK开发包也为用户提供了线程创建、使用的很好的封装,程序员仅仅想使用普通的类一样继承一个特定的接口Runable或者继承
14、一个已有的简单线程类Thread即可创建并使用Java的线程功能了。应用级线程一旦创建后,就交给了JVM管理,JVM内部维护这所有应用级以及JVM内部线程列表,用户可以通过指定JVM启动的参数来设置JVM的线程管理方式,是由JVM自己管理内部线程、完成线程通过工作,还是将应用线程直接绑到操作系统内核线程,并且由操作系统内核来完成线程同步等管理工作。下面会对这些参数一一进行介绍。 Java内部的线程同步管理或线程调度是通过一种监视器的技术来实现的,基本上的原理如下,我们将监视器比喻成一座建筑,而其中一些特别的房间里面的数据在同一时间只能有一个“人” 线程能够访问,当一个线程进入这个房间到它离开之
15、前,它可以独占的操作其中的数据,我们将线程进入这个建筑叫做“进入监视器”,线程进入这个特殊的房间叫做“获得监视器”,离开房间时叫“释放监视器”,离开建筑时叫做“退出监视器”。监视器除了监控一些数据之外,还可以监控一些代码,这样的代码叫做监视区域,在同一监视器中,一块监视区域的代码在同一时间只能够被一个线程所访问。同步数据或同步代码在Java程序中用Synchronized参数标明就可以了,从Java字节码编译器生成的虚拟机指令序列来看,编译器将操作指令monitorenter、monitorexit添加到具有Synchronized关键字的方法开始和结尾,而所有对具有Synchronized关
16、键字的类数据的操作前后也都添加了monitorenter、monitorexit操作指令,这样在虚拟机指令序列时JVM会调用monitorenter、monitorexit指令完成线程间的同步控制。 图2 Java虚拟机线程同步监视器 3 JAVA虚拟机参数分类说明 3.1 Java虚拟机标准参数 所谓的Java虚拟机标准参数指的就是所有的虚拟机实现都应该支持的参数,这部分参数基本上都是对虚拟机基本能力的调整,包括对运行模式、垃圾收集信息显示、显示版本信息、断言开关等,下面是以Solaris下1.4.2版本为例: 参数 使用说明 指明该Java VM是运行与32位环境还是64位环境,默认是运行
17、在32位环境下的,如果是配置了64位模式则需要操作系统也必须是64位的,当然CPU更需要是64位的。另外如果我们选择了-server参数,则就暗含了64位模式。 设置该JVM运行与Client 或者Server Hotspot模式,这两种模式从本质上来说是在JVM中运行不同的JIT代码,并且两者在JVM内部的接口是一致的。客户端模式优化的是系统启动时间更快,而服务端模式的优化则更关注与系统的整体性能。一般来说Client选项用于GUI的应用,Server选项多用于后台服务器应用。 备注 因为64的CPU兼容32位操作系统,而64位操作系统又是兼容32位执行程序 另外两者在编译策略、垃圾收集策略
18、、堆使用上也有所不同 -d32 -d64 -client -server -hotspot 在Hotspot类型的JVM中缺省使用,缺省为Client Hotspot模式。 指明JVM启动时要加载的类文件路径,Java虚拟机进程在启动时就会按照该参数后面指明的路径查找*.zip、*.jar、*.class文件,然后将这些包中的类文件加载到内存中。 JVM加载类文件的顺序是 Java程序员可以在程序内调用system.getProperty来获取用户通过-D参数传进来的系统属性信息。而命令行参数就是是JVM传递给main函数的调用参数 对于测试中的系统可以通过打开:gc开关,查看JVM每次垃圾收
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JAVA 虚拟机 性能参数 指导书
链接地址:https://www.31ppt.com/p-3159771.html