JVM参数配置
大致方向:JVM调优的目的是保证在一定吞吐量的情况下尽可能的减少GC次数,从而减少系统停顿时间,提高服务质量和效率。
其中减少GC次数的原则:
- 将新生代转换成老年代的数量降至最少(及时进行Minor GC回收新生代)
- 减少Full GC 次数
常用参数
-XX:+PrintGCDetails:打印GC的详细信息(冒号之后的+表示打印,-表示不打印)
-XX:+UseSerialGC : 使用串行回收器
-Xmx4000m :指定堆最大值为4000M( 等价于-XX:MaxHeapSize)。默认物理内存的1/4
-Xms4000m :指定堆初始化值为4000M( 等价于-XX:initialHeapSize)。默认物理内存的1/64
-Xmn2000m :设置新生代大小为2000M。
-Xss512k:设置栈大小为512k
设置堆内存大小
- -Xmx :指定堆最大值。默认物理内存的1/4
- -Xms :指定堆初始化值。默认物理内存的1/64
推荐:通常会将 -Xmx 与 -Xms两个参数配置成相同的值
public class Main {
/**
*堆内存大小配置
* -Xmx4000m 设置最大堆内存为4000m
* -Xms4000m 设置初始化堆内存为4000m
* @param args
*/
public static void main(String[] args) {
System.out.println("堆最大内存:"+Runtime.getRuntime().maxMemory()/1024/1024);
System.out.println("可用内存:"+Runtime.getRuntime().freeMemory()/1024/1024);
System.out.println("内存总量:"+Runtime.getRuntime().totalMemory()/1024/1024);
}
}
设置栈大小
-Xss
- 设置单个线程栈的大小,一般默认为 512-1024k
- 等价于 -XX:ThreadStackSize
设置新生代大小
-Xmn :设置年轻代大小。
整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。
- 此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
设置元空间大小
元空间的本质和永久代类似,都是对 JVM 规范中的方法区的实现。
不过元空间于永久代之间最大区别在于,元空间并不在虚拟中,而是使用本地内存,因此默认情况下,元空间的大小仅受本地内存限制。
- 元空间的默认大小在20m左右,通常会调大一点。
-XX:MetaspaceDetails=1024m
新生代比例大小配置
-XX:SurvivorRatio=8 eden:from:to = 8:1:1 (default)
-XX:SurvivorRatio=2 eden:from:to = 2:1:1
public class Main {
/**
* 新生代比例大小配置
* -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
* -Xmn1m 新生代最大可用值
*
*
*
* @param args
*/
public static void main(String[] args) {
byte[] b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1 * 1024 * 1024];
}
}
}
新生代和老年代比例配置
-XX:NewRatio=2 新生代和老年代的占比为1:2 (default)
public class Main {
/**
* 新生代与老年代比例大小配置
*
* -XX:NewRatio=2 新生代和老年代的占比为1:2
*
* @param args
*/
public static void main(String[] args) {
byte[] b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1 * 1024 * 1024];
}
}
}
设置垃圾的最大年龄
-XX:MaxTenuringThreshold=15(default)
新生代对象经过15次的回收就会进入老年代
小结
-Xmx4000m
-Xms4000m
-Xss1024k
-XX:MetaspaceSize=1024m
-XX:+PrintCommandLineFlags
-XX:+PrintGCDetails
//使用默认
-Xmn
-XX:SurvivorRatio
-XX:NewRatio
-XX:MaxTenuringThreshold
堆内存溢出问题
当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出
堆是存放对象的地方,那么只要在堆中疯狂的创建对象,那么堆就会发生内存溢出。
public class Main {
/**
*-Xms1m -Xmx1m -XX:+PrintGCDetails
*/
public static void main(String[] args) {
for (int i=0;i<100;i++)
{
Byte[] bytes = new Byte[1 * 1024 * 1024]; ///1M = 1024K = 1024*1024 字节
}
}
}
增大堆内存
-Xms100m -Xmx100m
栈溢出
通常产生于递归调用
public class Main {
/**
* -Xss10m
*/
private static int count;
public static void count()
{
// count++;
// count();
try
{
count++;
count();
}
catch (Throwable throwable)
{
System.out.println("最大深度:"+count);
}
}
public static void main(String[] args) {
count();
}
}
内存溢出和内存泄漏
内存溢出发生在申请堆内存空间时,内存不够用了。
比如你需要100M的空间,系统只剩90M了,这就叫内存溢出
内存泄漏是指创建一些对象,比如说IO流,数据库连接未关闭导致内存的持续占用,致使本该回收的内存空间依然被占用。而内存泄漏多了之后,就会导致内存溢出。
JVM命令工具
JVM常用命令
jps:JVM Process Status Tool 虚拟机进程状况工具
jps -l 输出主类全名,如果是Jar包,输出Jar包路径
-l : 输出主类全名或jar路径
-q : 只输出LVMID
-m : 输出JVM启动时传递给main()的参数
-v : 输出JVM启动时显示指定的JVM参数
jinfo:查看虚拟机各项参数
jps -l //获取LVMID
//查看打印GC日志的参数
jinfo -flag PrintGCDetails 12368
-XX:-PrintGCDetai