前言
通过虚拟机参数可以对虚拟机进行设置(如设置堆大小,栈深度等),可以对虚拟机进行跟踪(跟踪垃圾回收信息,类加载情况)。
通过对虚拟机参数的设置来解决诊断问题与性能优化。
参数的使用有三种
-XX:+<option> 开启参数
-XX:-<option> 关闭参数
-XX:<option>=<value> 将option参数的值设置为value
跟踪Java虚拟机垃圾回收
-XX:+PrintGC
使用参数-XX:+PrintGC 启动Java虚拟机,只要有GC就会输出内容。
每一次GC就会输出一行内容,这里一共有4次GC。
第一次GC为例:GC之前堆可用空间大约4M,GC执行完毕之后可用空间377k,当前堆的总空间大约16M。执行这一次GC使用的时间为0.0006926秒
-XX:+PrintGCDetails
查看更详细的GC内容.
//jvm options -Xmx20M -Xms5M -XX:+PrintGCDetails -XX:+UseSerialGC
//UseSerialGC 设置垃圾回收模式为串行的方式
public class HeapVmOptions2 {
public static void main(String[] args) {
byte[] bt = new byte[1*1024*1024];
bt = new byte[4*1024*1024];
}
}
[GC[DefNew: 622K->128K(1536K), 0.0017113 secs] 622K->464K(4992K), 0.0017395 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew: 1152K->0K(1536K), 0.0013924 secs][Tenured: 1488K->1488K(3456K), 0.0024423 secs] 1488K->1488K(4992K), [Perm : 2504K->2504K(21248K)], 0.0038614 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 1664K, used 92K [0x00000000f9a00000, 0x00000000f9bc0000, 0x00000000fa0a0000)
eden space 1536K, 6% used [0x00000000f9a00000, 0x00000000f9a171d8, 0x00000000f9b80000)
from space 128K, 0% used [0x00000000f9b80000, 0x00000000f9b80000, 0x00000000f9ba0000)
to space 128K, 0% used [0x00000000f9ba0000, 0x00000000f9ba0000, 0x00000000f9bc0000)
tenured generation total 7556K, used 5584K [0x00000000fa0a0000, 0x00000000fa801000, 0x00000000fae00000)
the space 7556K, 73% used [0x00000000fa0a0000, 0x00000000fa6142f8, 0x00000000fa614400, 0x00000000fa801000)
compacting perm gen total 21248K, used 2513K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 11% used [0x00000000fae00000, 0x00000000fb0747f8, 0x00000000fb074800, 0x00000000fc2c0000)
No shared spaces configured.
可以看到类似这的内容,出现了新生代(DefNew),老年代(Tenured),永久区(Perm )的情况更加细致。
-Xloggc
输出GC日志到指定文件里面
例如:
输出详细GC内容到c盘 log.txt文件中
-XX:+PrintGCDetails -Xloggc:c:/log.txt
跟踪Java类加载/卸载
-XX:+TraceClassLoading
查看类的卸载
-XX:+TraceClassUnloading
查看类的加载
系统参数查看
Java虚拟机中有很多参数可以配置,不同的配置对Java虚拟机的执行效果有很大的影响。有时候有必要获取实际的运行参数,Java虚拟机提供了一些参数来获取这些运行时的实际值。
-XX:+PrintVMOptions
运行时传入参数,那么控制台就会输出
VM option '+PrintVMOptions'
VM option '+PrintGC'
这个参数的作用就是输出启动时传给Java虚拟机的参数,但是这里只能打印出来显式的参数
-XX:+PrintCommandLineFlags
输出内容:
-XX:InitialHeapSize=133185408
-XX:MaxHeapSize=2130966528
-XX:+PrintCommandLineFlags
-XX:+PrintGC
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
可以看到不仅仅有设置的PrintCommandLineFlags 和 PrintGC 还有一些其他没有设置的参数,这些是隐式参数也可输出
-XX:+PrintFlagsFinal
这个参数可以输出所有的系统信息,达到几百个之多。
Java堆的参数设置
最大值和最小值
public class HeapVmOptions {
public static void main(String[] args) {
//maxMemory : 表示Java虚拟机最多能从操作系统中使用的内存
//totalMemory : 表示java虚拟机现在已经从操作系统那里获取来的内存大小
//freeMemory : 表示java虚拟机现在已经从操作系统那里获取来的内存,然后又没有使用的大小。
System.out.println("Max Memory=" + Runtime.getRuntime().maxMemory() + " bytes");
System.out.println("Free Memory=" + Runtime.getRuntime().freeMemory() + " bytes");
System.out.println("Total Memory=" + Runtime.getRuntime().totalMemory() + " bytes");
byte[] bt = new byte[1*1024*1024];
System.out.println("分配了1M空间给数组");
System.out.println("Max Memory=" + Runtime.getRuntime().maxMemory() + " bytes");
System.out.println("Free Memory=" + Runtime.getRuntime().freeMemory() + " bytes");
System.out.println("Total Memory=" + Runtime.getRuntime().totalMemory() + " bytes");
bt = new byte[4*1024*1024];
System.out.println("分配了4M空间给数组");
System.out.println("Max Memory=" + Runtime.getRuntime().maxMemory() + " bytes");
System.out.println("Free Memory=" + Runtime.getRuntime().freeMemory() + " bytes");
System.out.println("Total Memory=" + Runtime.getRuntime().totalMemory() + " bytes");
bt = null;
System.out.println("清空数组");
System.out.println("Max Memory=" + Runtime.getRuntime().maxMemory() + " bytes");
System.out.println("Free Memory=" + Runtime.getRuntime().freeMemory() + " bytes");
System.out.println("Total Memory=" + Runtime.getRuntime().totalMemory() + " bytes");
}
}
运行参数:
-Xmx20M -Xms5M -XX:+PrintGCDetails -XX:+UseSerialGC
设置最大内存20M,最小内存5M,以串行化进行垃圾回收,打印垃圾回收详细信息
输出结果:
Max Memory=20316160 bytes
Free Memory=4472600 bytes
Total Memory=5111808 bytes
[GC[DefNew: 624K->128K(1536K), 0.0018178 secs] 624K->466K(4992K), 0.0018725 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
分配了1M空间给数组
Max Memory=20316160 bytes
Free Memory=3556768 bytes
Total Memory=5111808 bytes
[GC[DefNew: 1180K->0K(1536K), 0.0014202 secs][Tenured: 1490K->1490K(3456K), 0.0024887 secs] 1518K->1490K(4992K), [Perm : 2505K->2505K(21248K)], 0.0039385 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
分配了4M空间给数组
Max Memory=20316160 bytes
Free Memory=3641424 bytes
Total Memory=9441280 bytes
清空数组
Max Memory=20316160 bytes
Free Memory=3641424 bytes
Total Memory=9441280 bytes
Heap
def new generation total 1664K, used 108K [0x00000000f9a00000, 0x00000000f9bc0000, 0x00000000fa0a0000)
eden space 1536K, 7% used [0x00000000f9a00000, 0x00000000f9a1b100, 0x00000000f9b80000)
from space 128K, 0% used [0x00000000f9b80000, 0x00000000f9b80000, 0x00000000f9ba0000)
to space 128K, 0% used [0x00000000f9ba0000, 0x00000000f9ba0000, 0x00000000f9bc0000)
tenured generation total 7556K, used 5586K [0x00000000fa0a0000, 0x00000000fa801000, 0x00000000fae00000)
the space 7556K, 73% used [0x00000000fa0a0000, 0x00000000fa6149f8, 0x00000000fa614a00, 0x00000000fa801000)
compacting perm gen total 21248K, used 2515K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 11% used [0x00000000fae00000, 0x00000000fb074e98, 0x00000000fb075000, 0x00000000fc2c0000)
说明:
这里设置的最大可用为20M ,
-Xmn
Java堆里面存储的是对象,对象按照垃圾回收来划分的话,区分为新生代,老年代,永久区。
设置的新生代的绝对大小,设置一个较大的新生代会让老年代减小,新生代的大小一般设置在堆大小的3分之一或者4分之一
-XX:NewRatio
设置新生代与老年代的大小比例, -XX:NewRatio=2 ,那么新生代的大小是老年代的2倍
-XX:SurvivorRatio=2
设置新生代中eden空间与from/to空间大小比例,这里设置eden的空间是from/to的两倍
设置参数: -Xmn1M -XX:SurvivorRatio=2
输出如下:新生代总空间1M,eden512k,from/to正好是一半256k,
Heap
def new generation total 768K, used 39K [0x00000000f9a00000, 0x00000000f9b00000, 0x00000000f9b00000)
eden space 512K, 7% used [0x00000000f9a00000, 0x00000000f9a09fc8, 0x00000000f9a80000)
from space 256K, 0% used [0x00000000f9a80000, 0x00000000f9a80000, 0x00000000f9ac0000)
to space 256K, 0% used [0x00000000f9ac0000, 0x00000000f9ac0000, 0x00000000f9b00000)
堆信息导出
堆溢出的时候导出信息到d盘1.dump文件中
import java.util.LinkedList;
import java.util.List;
public class HeapOfMenory {
public static void main(String[] args) {
List<byte[]> list = new LinkedList<byte[]>();
while(true){
byte[] bt = new byte[1*1024*1024];
list.add(bt);
}
}
}
参数
-Xmx20M -Xms5M -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/1.dump
输出(可以发现导出文件已经生产)
java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:/1.dump ...
Heap dump file created [18946569 bytes in 0.019 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
方法区配置
在1.6和1.7版本的Hotspot版本虚拟机中通过 -XX:PermSize和-XX:MaxPermSize设置最小值和最大值.
在1.8版本的Hotspot虚拟机中通过-XX:MaxMetaspaceSize来设置最大值
栈配置
通过-Xss配置每个线程的栈大小
直接内存配置
最大可用直接内存可用通过参数-XX:MaxDirectMemorySize来设置,默认值是最大的堆空间。当直接内存使用达到最大值,就会触发垃圾回收,如果无法回收就会抛出异常内存溢出.
虚拟机的工作模式Client和Server
Java虚拟机有两种工作模式Client和Server。
Server适用于长期稳定运行的系统,它启动会收集更多的系统信息,启动会慢。
Client启动比较快,适用于运行时间不长,需要马上启动的系统。
通过Java -version 可以看到当前的Java虚拟机启动模式。
可以通过 -client 和 -server 来设置Java虚拟机的启动模式