实战java虚拟机02- 常用虚拟机参数

实战java虚拟机 学习笔记

jdk版本
这里介绍一个联接的方式,设置java_home的方法:

mklink /J "D:\study\jdk\jdk_link" "D:\study\jdk\jdk16\jdk1.6.0_45"

只需将path或者java_home 设置为D:\study\jdk\jdk_link即可。


垃圾回收

-XX:PrintGC
简单的GC参数,只要发生GC,就会打印如下日志:

[GC 6902K->5376K(7872K), 0.0056952 secs]
[GC-- 6400K->6400K(7872K), 0.0006237 secs]
[Full GC 6400K->1216K(6144K), 0.0076061 secs]

进行了3次GC,且第三次为FullGC,每次GC占用1行,每一行的日志含义如下:

[GC类型   GC前堆空间使用量 -> GC后堆空间使用量(堆空间总量),GC所花费的时间]

-XX:PrintGCDetails
打印更为详尽的信息,如下:

[GC [PSYoungGen: 1778K->288K(2368K)] 6898K->5408K(7872K), 0.0008094 secs] [Times: user=0.05 sys=0.00, real=0.00 secs] 
[GC-- [PSYoungGen: 1353K->1353K(2368K)] 6473K->6473K(7872K), 0.0004702 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC [PSYoungGen: 1353K->0K(2368K)] [PSOldGen: 5120K->1215K(3648K)] 6473K->1215K(6016K) [PSPermGen: 3481K->3481K(21248K)], 0.0069306 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 

分析得知,第一次GC为新生代GC,GC后,新生代的空间由1778K降低到288K,堆内存空间由6898K降低为5408K。
第三次GC为Full GC,

Full GC = 新生代GC+年老代GC+永久代GC
  • 新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。
  • 老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。 Major GC的速度一般会比Minor GC慢10倍以上。
Serial收集器中的新生代名为“Default New Generation”,所以显示的是“[DefNew”。
ParNew收集器,新生代名称就会变为“[ParNew”,意为“Parallel New Generation”。
Parallel Scavenge收集器,新生代称为“PSYoungGen”,老年代和永久代同理,名称也是由收集器决定。

,Full GC后,新生代被清空,老年代由5120K降低为1215K,堆空间由6473K降低为1215K,永久代则不变 : 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。 最后显示的是GC所花费的时间。
使用-XX:PrintGCDetails后,在虚拟机退出前,打印堆的信息:

Heap
 PSYoungGen      total 2368K, used 1127K [0x00000000ffd60000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 55% used [0x00000000ffd60000,0x00000000ffe79e50,0x00000000fff60000)
  from space 320K, 0% used [0x00000000fff60000,0x00000000fff60000,0x00000000fffb0000)
  to   space 320K, 0% used [0x00000000fffb0000,0x00000000fffb0000,0x0000000100000000)
 PSOldGen        total 3648K, used 3263K [0x00000000ff800000, 0x00000000ffb90000, 0x00000000ffd60000)
  object space 3648K, 89% used [0x00000000ff800000,0x00000000ffb2ff98,0x00000000ffb90000)
 PSPermGen       total 21248K, used 3534K [0x00000000fa600000, 0x00000000fbac0000, 0x00000000ff800000)
  object space 21248K, 16% used [0x00000000fa600000,0x00000000fa973a58,0x00000000fbac0000)

详细描述当前堆各个区间(新生代+年老代+永久代)的使用情况。

[0x00000000fa600000, 0x00000000fbac0000, 0x00000000ff800000)

表示当前区间的下界,当前上界,上界.

-XX:+PrintHeapAtGC
每次GC前后,分别打印堆的信息, 使用这个参数可以很好的观察分析GC对堆空间的影响。

-XX:+PrintGCTimeStamps
该参数会在每次GC发生时,额外输出GC发生的时间,该时间为虚拟机启动后的时间偏移量(单位秒):

0.174: [GC 6906K->5392K(7872K), 0.0008817 secs]
0.175: [GC-- 6457K->6457K(7872K), 0.0007497 secs]
0.176: [Full GC 6457K->1216K(6016K), 0.0065074 secs]

在虚拟机启动后0.174,0.175,0.176秒发生了三次GC.

-XX:+PrintGCApplicationConcurrentTime,-XX:+PrintGCApplicationStoppedTime
GC会引起应用程序停顿,上述命令分别记录程序运行的时间和程序停顿时间,如下:

Application time: 0.0383547 seconds
[GC 6946K->5376K(7872K), 0.0135654 secs]
Total time for which application threads were stopped: 0.0136764 seconds

-Xloggc:filename
虚拟机允许将GC日志以文件的形式输出,例:

-Xloggc:log/gc.log

输出到log文件夹下gc.log 。 注意log文件夹一定要存在,否则不会生成gc.log文件,也不会报错。


类加载、卸载追踪

Java程序的运行离不开类的加载,为了更好的理解程序的执行,有时候需要知道系统加载了哪些类。
-verbose:class
-verbose:class跟踪类的加载和卸载

-XX:+TraceClassLoading
使用-XX:+TraceClassLoading追踪类的加载

-XX:+TraceClassUnloading
-XX:+TraceClassUnloading 追踪类的卸载。

-XX:+PrintClassHistogram
当Ctrl+Break发生时打印当前类信息柱状图。

不能理解这个是什么意思。
这里写图片描述


系统参数

-XX:+PrintVMOptions
打印虚拟机收到的命令行显示参数,如下:

VM option '+PrintClassHistogram'
VM option '+PrintVMOptions'

表示虚拟机启动时,命令行明确指定了 PrintClassHistogram和PrintVMOptions参数

-XX:+PrintCommandLineFlags
打印出传递给虚拟机的显示和隐式参数。这些参数并不一定是在命令行显示指定的,还有一些是虚拟机自行设置的。

-XX:+PrintFlagsFinal
打印所有的系统参数值,最多可能达到500多行的输出。


堆配置参数

最大值和初始值
- -Xms10m 设置初始堆空间10m
- -Xmx20m 设置最大堆空间20m

-Xms10m -Xmx20m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails 命令,执行如下java代码:

public static void main(String[] args) {
    System.out.println("max mem="+Runtime.getRuntime().maxMemory() +" bytes");
    System.out.println("free mem="+Runtime.getRuntime().freeMemory() +" bytes");
    System.out.println("total mem="+Runtime.getRuntime().totalMemory()+" bytes");
}

输出如下结果:

-XX:InitialHeapSize=10485760 -XX:MaxHeapSize=20971520 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails .....省略......
max mem=18677760 bytes
free mem=9926616 bytes
total mem=10682368 bytes
Heap
 PSYoungGen      total 3584K, used 799K  ......省略......
 PSOldGen        total 6848K, used 0K  ......省略......
 PSPermGen       total 21248K, used 3448K  ......省略......

可以看出来
InitialHeapSize=10485760 = 10 * 1024 * 1024 =10M;
MaxHeapSize=20971520 = 20 * 1024 * 1024 =20M; 而最大可用内存为:18677760 bytes,略小于20m

实际工作中,可以将-Xms和-Xmx设置为相等,这样做的好处是减少程序运行时进行的垃圾回收次数,从而提高性能。

新生代配置-Xmn
使用-Xmn设置新生代的大小,设置一个较大的新生代会减少老年代的大小,这个参数对系统性能以及GC行为有很大影响。

-XX:SurvivorRatio
-XX:SurvivorRatio设置新生代中:eden/form = eden/to的比例关系

-XX:NewRatio
XX:NewRatio设置 年老代/新生代 的比例关系

堆内分配参数总览
这里写图片描述


堆溢处理:
如果堆内存空间不足,可能会抛出内存溢出异常(OOM):java.lang.OutOfMemoryError: Java heap space;

-XX:+HeapDumpOnOutOfMemoryError
JAVA虚拟机提供参数,可使用该参数在发生OOM异常时,导出整个堆信息

-XX:HeapDumpPath
使用该参数,配合-XX:+HeapDumpOnOutOfMemoryError使用,可指定导出堆信息的路径。

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump

-XX:OnOutOfMemory
在发生OOM发生时,执行一个脚本文件,下面给出一个在发生OOM时导出线程转存的例子:
准备脚本文件:d:/printstack.bat

D:\study\jdk\jdk_link\bin\jstack -F %1 > D:/a.txt

执行命令参数:

"-XX:OnOutOfMemoryError=d:/dprintstack.bat %p"

方法区配置-永久代
-XX:PermSize
初始永久代大小

-XX:MaxPermSize
最大永久代大小

元数据区-XX:MaxMetasapceSize
jdk8中,永久区被彻底移除,使用了新的元数据区存放元数据。
使用-XX:MaxMetasapceSize设置永久区大小。


栈配置-Xss
使用-Xss设置线程的栈大小


直接内存配置-XX:MaxDirectMemorySize
默认值为-Xmx即最大堆内存的大小。 它的含义是DirectByteBuffer能分配的空间的限额,当达到设定值时,即触发Full GC。
DirectByteBuffer有几处值得注意的地方: JVM调优的陷阱

  • 1、DirectByteBuffer没有finalizer,它的native memory的清理工作是通过sun.misc.Cleaner自动完成的。
  • 2、sun.misc.Cleaner是一种基于PhantomReference的清理工具,比普通的finalizer轻量些。

Oracle/Sun JDK 6中的HotSpot VM只会在old gen GC(full GC/major GC或者concurrent GC都算)的时候才会对old gen中的对象做reference processing,而在young GC/minor GC时只会对young gen里的对象做reference processing。
也就是说,做full GC的话会对old gen做reference processing,进而能触发Cleaner对已死的DirectByteBuffer对象做清理工作。
而如果很长一段时间里没做过GC或者只做了 young GC的话则不会在old gen触发Cleaner的工作,那么就可能让本来已经死了的、但已经晋升到old gen的DirectByteBuffer关联的native memory得不到及时释放。

  • 3、为DirectByteBuffer分配空间过程中会显式调用System.gc(),以期通过full GC来强迫已经无用的DirectByteBuffer对象释放掉它们关联的native memory:

教训是:如果你在使用Oracle/Sun JDK 6,应用里有任何地方用了direct memory,那么使用-XX:+DisableExplicitGC要小心。如果用了该参数而且遇到direct memory的OOM,可以尝试去掉该参数看是否能避开这种OOM。如果担心System.gc()调用造成full GC频繁,可以尝试下面提到 -XX:+ExplicitGCInvokesConcurrent 参数


虚拟机的工作模式

java虚拟机支持Client和Server两种运行模式。

$ java -version 
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)

由此可见默认的运行模式是:Server VM,与Client模式相比,Server模式启动较慢 ,因为Server模式会尝试收集更多的系统性能信息,使用更复杂的优化算法对程序进行优化。因此,当系统完全启动并进入翁定期后,Server模式的执行速度会远远快于Client模式。因此,对于长期运行的系统,使用-server参数启动。

64位操作系统,更倾向与默认是用server模式。

想要查看server模式和client模式的区别,可以使用前面的参数,打印所有的系统参数值:

-XX:+PrintFlagsFinal 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值