深入JVM-常用Java虚拟机参数
一、跟踪调试参数
1.1 跟踪垃圾回收-读懂虚拟机日志
Java的一大特色就是支持自动的垃圾回收(GC),但是有时候,如果垃圾回收频繁出现,或者占用了太长的CPU时间,就不得不引起重视。此时,就需要一些跟踪参数来进一步甄别垃圾回收器的效率和效果。
最简单的一个GC参数是-XX:+PrintGC,使用这个参数启动Java虚拟机后,只要遇到GC,就会打印日志。
如果需要更加详细的信息,则可以使用-XX:+PrintGCDetails参数。他的输出可能如下:

从这个输出可以看到,系统经历了3次GC,第一次仅为新生代GC,回收的效果是新生代从回收前的8MB左右降到了1M左右。整个堆从22MB左右降到了17MB。
第二次为Full GC,它同时回收了新生代、老年代和永久区。从日志显示,新生代在这次GC中没有释放空间(严格来说,这是GC日志的一个小bug,事实上,在这次Full GC完成后,新生代被清空,由于GC日志输出时机的关系,各个版本的JDK日志多少有些不太精确的地方),老年代从16MB降到了13MB。整个堆大小从26MB左右降到了13MB左右(这个大小完全与老年代实际大小相等,因此可以推断,新生代实际上已被清空)。永久区的大小没有变化。日志的最后,显示了GC花费的时间,其中user表示用户态CPU耗时,sys表示系统CPU耗时,real表示GC实际经历的时间。
如果需要更全面的堆信息,还可以使用参数-XX:+PrintHeapAtGC。他会在每次GC前后分别打印堆的信息。
如果需要分析GC发生的时间,还可以使用-XX:+PrintGCTimeStamps参数,该参数会在每次GC发生时,额外输出GC发生的时间,该输出时机为虚拟机启动后的时间偏移量。
默认情况下,GC的日志会在控制台输出,这不便于后续分析和定位问题。为此,虚拟机允许将GC日志以文件的形式输出,可以使用参数-Xloggc指定。
1.2 类加载/卸载的跟踪
一般情况下,系统加载的类存在于文件系统中,以jar的形式打包或者以class文件的形式存在,可以直接通过文件系统查看。但是随着动态代理、AOP等技术的普遍使用,系统也ji'ke'neng极可能在运行时动态生成某些类,这些类相对比较隐蔽,无法通过文件系统找到。
可以使用参数-verbose:class跟踪类的加载和卸载,也可以单独使用参数-XX:+TraceClassLoading跟踪类的加载,使用参数-XX:+TraceClassUnloading跟踪类的卸载。
Java虚拟机还允许研发人员在运行时打印、查看系统中类的分布情况,只要在系统启动时加上-XX:+PrintClassHistogram参数,然后在Java控制台按下Ctrl+Break组合键,控制台就会显示当前的类信息柱状图。
1.3 系统参数查看
参数-XX:+PrintVMOptions可以在程序运行时,打印虚拟机接收到的命令行显式参数。
参数-XX:+PrintCommandLineFlags可以打印传递给虚拟机的显式和隐式参数。
二、学习堆的配置参数
2.1 最大堆和初始堆的设置
- Xms:初始堆
- Xmx:最大堆
在实际工作中,也可以直接将初始堆-Xms和最大堆-Xmx设置相等,这样好处是可以减少程序运行时进行的垃圾回收次数,从而提高程序的性能。
2.2 新生代的配置
参数-Xmn可以用于设置新生代的大小。设置一个较大的新生代会减小老年代的大小,这个参数对系统性能以及GC行为有很大的影响,新生代的大小一般设置为整个堆空间的1/3到1/4左右。
参数-XX:SurvivorRatio用来设置新生代中eden空间和from/to空间的比例关系,他的含义如下:
-XX:SurvivorRatio=eden/from=eden/to
实际工作中,堆分布的基本策略是:尽可能将对象预留在新生代,减少老年代GC的次数。
除了可以使用-Xmn指定新生代的绝对大小外,还可以使用参数-XX:NewRatio来设置新生代和老年大的比例,他的含义如下:
-XX:NewRatio=老年代/新生代

2.3 堆溢出处理
在Java程序的运行过程中,如果堆空间不足,则有可能抛出内存溢出错误(OutOfMemory),简称OOM。一旦发生这类问题,系统就会被迫退出。如果发生在生产环节,可能会引起严重的业务中断。为了不断改善系统,避免或减少这类错误的发生,需要在发生错误时,获得尽可能多的现场信息。Java虚拟机提供了参数-XX:+HeapDumpOnOutOfMemoryError,使用该参数,可以再内存溢出时导出整个堆信息。和他配合使用的还有-XX:HeapDumpPath,可以指定导出堆的存放路径。
三、非堆内存的参数配置
3.1 方法区配置
方法区主要存放类的元信息。
在JDK1.6和JDK 1.7等版本中,可以使用-XX:PermSize和-XX:MaxPermSize配置永久区大小。其中-XX:PermSize表示初始的永久区大小,-XX:MaxPermSize表示最大永久区。
在JDK 1.8中,永久区被彻底移除,使用了新的元数据区存放类的元数据。默认情况下,元数据区只受系统可用内存的限制,但依然可以使用参数-XX:MaxMetaspaceSize指定元数据区的最大可用值。
3.2 栈配置
通过-Xss指定线程的栈大小。
3.3 直接内存配置
最大可以直接内存可以使用参数-XX:MaxDirectMemorySize设置,如不设置,默认值为最大dui堆空间,即-Xmx。当直接内存使用量达到-XX:MaxDirectMemorySize时,就会触发垃圾回收,如果垃圾回收不能有效释放足够空间,直接内存溢出依然会引起系统的OOM。
四、虚拟机的工作模式
目前Java虚拟机支持Client和Server两种运行模式。默认情况下,虚拟机会根据当前计算机系统环境自动选择运行模式。使用-version参数可以查看当前的模式,如下:
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
与Client模式相比,Server模式启动较慢,因为Server模式会尝试收集更多的系统性能信息,使用更复杂的优化算法对程序进行优化。因此,当系统完全启动并进入运行稳定期后,Server模式的执行速度会远远快于Client模式。
深入JVM-常用Java虚拟机参数的更多相关文章
- Java虚拟机四 常用Java虚拟机参数
主要涉及的知识点: 1.跟踪Java虚拟机的垃圾回收和类加载等信息: 2.配置Java虚拟机的堆空间: 3.配置永久区和Java栈. 4.学习虚拟机的服务器和客户端模式. 1.1 跟踪垃圾回收 Jav ...
- 如何设置java虚拟机参数
这两天在看java虚拟机,从书上看到可以自己设置java虚拟机的参数,可以方便开发人员进行系统调优和故障排查 Ecplise设置java虚拟机参数: window-->preferences-- ...
- java虚拟机参数设置 jvm参数设置
java进程命令行使用方式如下: java [-options] class [args...] -options 表示虚拟机的启动参数, class为带有main()函数的java类的全名称 arg ...
- Java虚拟机参数设置(转)
今天在加载一幅图片时,eclipse报出如下错误: “Exception in thread "main" java.lang.OutOfMemoryError: Java hea ...
- JVM之Java虚拟机详解
这篇文章解释了Java 虚拟机(JVM)的内部架构.下图显示了遵守Java SE 7 规范的典型的 JVM 核心内部组件. 上图显示的组件分两个章节解释.第一章讨论针对每个线程创建的组件,第二章节讨论 ...
- JVM总结-Java 虚拟机是怎么识别目标方法(上)
重载与重写 在 Java 程序里,如果同一个类中出现多个名字相同,并且参数类型相同的方法,那么它无法通过编译.也就是说,在正常情况下,如果我们想要在同一个类中定义名字相同的方法,那么它们的参数类型必须 ...
- JVM(三)-java虚拟机类加载机制
概述: 上一篇文章,介绍了java虚拟机的运行时区域,Java虚拟机根据不同的分工,把内存划分为各个不同的区域.在java程序中,最小的运行单元一般都是创建一个对象,然后调用对象的某个 方法.通过上一 ...
- Java JVM——5.Java虚拟机栈
虚拟机栈概述 由于跨平台性的设计,Java 的指令都是根据栈来设计的.不同平台CPU架构不同,所以不能设计为基于寄存器的. 栈实现的优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功 ...
- JVM(Java虚拟机)详解(JDK7)
1.Java内存区域 运行时数据区域: Java 虚拟机在执行Java程序时,定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁.另外一些则是与线程 ...
随机推荐
- list转datatable
/// <summary> /// 将泛类型集合List类转换成DataTable /// </summary> /// <param name="list&q ...
- Verilog代码规范I
Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...
- SqlServer——批量操作(批量添加,删除)
批量添加数据: 一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , fir ...
- JavaScript变量的作用域和函数的作用域的区别
变量作用域和函数作用域都涉及到变量值的变化,本文旨在让大家明白他们之间的区别 变量的作用域: 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接 ...
- Linux中TFTP使用详解
FTP协议简介TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现. linux服务器端tftp-server的配置1.安装tftp服务器需要安装xinetd(守护tftp).tftp和 ...
- iOS 'The sandbox is not sync with the Podfile.lock'问题解决
问题描述: github下载的Demo,很多时候使用到CocoaPods,有的时候因为依赖关系或者版本问题不能编译运行.出现例如The sandbox is not sync with the Pod ...
- re模块(正则表达式)
re 模块:正则表达式import re 内置模块: 1> re.match(pattern,string) pattern:就是正则表达式 string:被操作的对象 match,search ...
- Linux_Shell_脚本参数接收键盘输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #!/bin/bash #提示"请输入姓名"并等待30秒,把用户的输入保存入变量name ...
- git初体验(七)多账户的使用
多github帐号的SSH key切换 我有两个github帐号,一个是个人所用,一个是为公司项目所用.如果是单用户(single-user),很方便,默认拿id_rsa与你的github服务器的公钥 ...
- JQuery 判断浏览器及其版本
JQuery 中用 方法 jQuery.browser 来判断浏览器,返回值可以为: safari opera msie mozilla. 当然有时候我们还需要区分版本 这就要用到 jQuery.br ...