JVM参数调优
JVM参数配置
JVM提供了诸多的参数进行JVM各个方面内存大小的设置,为Java应用进行优化提供了诸多的工具,本文将会详细分析各个参数的功能与使用。
常见参数配置
-XX:+PrintGC 每次触发GC的时候打印相关日志
-XX:+UseSerialGC 串行回收
-XX:+PrintGCDetails 更详细的GC日志
-Xms 堆初始值
-Xmx 堆最大可用值
-Xmn 新生代堆最大可用值
-XX:SurvivorRatio 用来设置新生代中Eden空间和from/to空间的比例.
-XX:NewRatio 配置新生代与老年代占比 1:2
含以-XX:SurvivorRatio=Eden/from=den/to
总结:在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,
这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。
-XX:SurvivorRatio 用来设置新生代中Eden空间和from/to空间的比例.
总结补充:
- 初始堆内存与电脑内存有关,默认4G 。
- 对于新生代最大可用值,满了发生Minor GC
- 触发Full GC ,新生代、老年代都会一起回收了
堆的初始值和最大值一定要相等,不相等的情况下,垃圾不停的回收,不停的申请,不停的回收 .....
- 垃圾回收时候 其他线程要停止,停顿一下( 如果不暂停,再次期间产生的新的垃圾不能回收。)。如果堆内存和最大不同,则不停回收。那么程序断断续续的进行,非常不好。大家要注意!
- 新生代小于老年代 。新生代回收的频率高,老年代低。 让新生代去频繁收集 所以调小一些 新生代:老年代=1:2 新生代占比越小越频繁 老年代打不频繁
实战一、堆内存大小配置
package jvmTest; //打印堆的基本内存信息 public class Test02 { public static void main(String[] args) { System.out.print("最大内存"); System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M"); System.out.print("可用内存"); System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M"); System.out.print("已经使用内存"); System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); } }
这是默认的堆存的状态
进行设置: -Xmx20m -Xms5m 初始5m 最大20m
运行结果:
已使用内存 根据初始值申请来的 !
来4M的内存看看:
package jvmTest; //打印堆的基本内存信息 public class Test02 { public static void main(String[] args) { byte[] b = new byte[4 * 1024 * 1024]; //4M System.out.print("最大内存"); System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M"); System.out.print("可用内存"); System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M"); System.out.print("已经使用内存"); System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); } }
运行结果:
使用内存 > 9M
但是不能申请25M给它哦,会堆溢出的~大家可以试试
设置新生代比例参数
使用示例: -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
说明:堆内存初始化值20m,堆内存最大值20m,新生代最大值可用1m,Eden空间和from/to空间的比例为2/1 (2:1:1)
Eden 默认 比S0、S1要大。因为S0、S1要复制的不要太大了
package jvmTest; //打印堆的基本内存信息 public class Test02 { public static void main(String[] args) { System.out.println("ssssss"); byte[] b = null; for (int i = 0; i < 10; i++) { b = new byte[1 * 1024 * 1024]; } } }
结果:
出现框框内的 说明内存不够 进行垃圾回收了
下面的分配:
配置新生代的
Eden空间和from/to空间的比例为2/1 2:1:1 结果展示完美
下面这么配置一下看看:
-XX:+PrintGCDetails -XX:+UseSerialGC
结果没有回收哦
最大始值设置20M时候会有 GC回收日志
因为之前这段代码运行时候 需要的内存是 10M i=10嘛 但是这时候新生代最大可用值是1M 这时候空间不够 为了够用 不停的回收 内存不够了就会不停的回收
设置新生代与老年代比例参数
使用示例: -Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC -XX:NewRatio=2
说明:堆内存初始化值20m,堆内存最大值20m,新生代最大值可用1m,eden空间和from/to空间的比例为2/1
新生代和老年代的占比为1/2
哇,竟然回收了三次!
新生代与老年的的占比是 1:2 看到eden+from+to : 1369 大致是哦
当然我们可以看下默认占比
大致为:13696:6784=1:2
补充Tomca调优经验:
经验结论:
- 垃圾回收次数和设置最大堆内存大小无关,只和初始内存有关系。初始内存会影响吞吐量。
- 堆的初始值和最大堆内存一致,并且初始堆越大就会高。
- 初始堆值和最大堆内存内存越大,吞吐量就越高。
- 最好使用并行收集器,因为并行收集器速度比串行吞吐量高,速度快。
- 设置堆内存新生代的比例和老年代的比例最好为1:2或者1:3。
- 减少GC对老年代的回收。