四:JVM调优与常见异常处理方案
Posted wlwl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四:JVM调优与常见异常处理方案相关的知识,希望对你有一定的参考价值。
在jvm调优之前,我们必须先了解jvm的内存模型与GC回收机制,这些在我前面的文章里面有介绍!接下来我们通过一个案例来调整jvm性能。
一:调优案例:
1.1 编写demo
import java.text.DecimalFormat; /** -XX:+PrintGC GC回收的时候打印相关日志 -XX:+UseSerialGC 串行回收 -XX:+PrintGCDetails 显示详细的GC日志 -Xms 堆初始值 -Xmx 堆最大可用值 -XX:SurvivorRatio 新生代中eden空间和from(s0),to(s1)空间的比例. -XX:NewRation= 新生带与老年代的比例 -Xss 栈的大小(栈的深度) */ public class JVMDemo { public static void main(String[] args) throws InterruptedException { // 最大内存 long maxMemory = Runtime.getRuntime().maxMemory(); System.out.println("最大堆内存为: "+format(maxMemory)+"MB"); // 已经使用内存 long totalMemory = Runtime.getRuntime().totalMemory(); System.out.println("已使用堆内存: "+format(totalMemory)+"MB"); // 当前剩余内存 long freeMemory = Runtime.getRuntime().freeMemory(); System.out.println("剩余堆内存为: "+format(freeMemory)+"MB"); byte[] b1 = new byte[4 * 1024 * 1024]; System.out.println("-----分配了4m堆内存-----"); // 当前剩余内存 long freeMemory2 = Runtime.getRuntime().freeMemory(); System.out.println("剩余堆内存为: "+format(freeMemory2)+"MB"); } /** * 将堆内存单位格式化成 MB */ static private String format(long maxMemory) { float num = (float) maxMemory / (1024 * 1024); DecimalFormat df = new DecimalFormat("0.00");// 格式化小数 String s = df.format(num);// 返回的是String类型 return s; } }
1.2 配置参数,打印jvm信息: 右键 --> Run As --> Run Configurations... --> Arguments --> VM arguments 输入配置信息 -XX:+PrintGCDetails -XX:+UseSerialGC
1.3 运行java代码, 查看jvm信息
// 这些信息与电脑配置参数有关,我们的具体数据可能不一样,但是内存模型数据比例是一样的
最大堆内存为: 1890.81MB // 大约1900MB
已使用堆内存: 119.88MB // 已用120MB
剩余堆内存为: 117.89MB // 剩余117MB
-----分配了4m堆内存-----
剩余堆内存为: 113.89MB // 用了4mb后还剩113MB
Heap
def new generation total 38080K, used 6805K [0x0000000085c00000, 0x0000000088550000, 0x00000000ae800000)
// 可以看出新生代中默认 eden区 from区 to区比例为 33856:4224:4224 即 8:1:1
eden space 33856K, 20% used [0x0000000085c00000, 0x00000000862a57a8, 0x0000000087d10000)
from space 4224K, 0% used [0x0000000087d10000, 0x0000000087d10000, 0x0000000088130000)
to space 4224K, 0% used [0x0000000088130000, 0x0000000088130000, 0x0000000088550000)
// 老年代和新生代默认比例为 84672:(33856+4224+4224) 即2:1
tenured generation total 84672K, used 0K [0x00000000ae800000, 0x00000000b3ab0000, 0x0000000100000000)
the space 84672K, 0% used [0x00000000ae800000, 0x00000000ae800000, 0x00000000ae800200, 0x00000000b3ab0000)
// 元空间
Metaspace used 3652K, capacity 4600K, committed 4864K, reserved 1056768K
class space used 410K, capacity 428K, committed 512K, reserved 1048576K
1.4 jvm常见参数含义
1.5 调优总结:
1.将初始的堆大小与最大堆大小相等,来垃圾回收次数从而提高效率。
2.将新生代或老年代的比例设置为1/3 或者 1/4,让GC尽量去新生代去回收。
-Xms2000m -Xmx2000m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:NewRatio=4
此时重新运行java类, 可以对比jvm信息
1.6 Tomcat修改JVM参数: linux系统修改tomcat/bin/catalina.sh文件,win系统修改tomcat/bin/catalina.bat文件。
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"
====================================================================
什么是内存泄漏及如何避免
内存泄漏即:对象可达但不可用,一个对象不再需要使用本该回收时,另一个正在使用的对象却持有它的引用,导致无法回收停留在堆内中。
防止内存泄露:
1.尽早释放无用对象的引用, 将不需要使用的对象设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄漏。
2.程序进行字符串处理时,尽量避免使用String,而应该使用StringBuffer。
3.尽量少用静态变量
4.尽量运用对象池技术以提高系统性能
Jvm常见异常处理方案
内存泄漏: java.lang.OutOfMemory Error:Java heap space
解决思路: 1. 先查看是不是内存泄漏,如果是通过GC Root的路径来排查
2. 查看堆内存是否有对象没释放。
3. 加大物理内存 –Xms, -Xmx,最好-Xms = -Xmx,减少内存扩展的开销。
控制参数: -Xms (starting 堆的起始大小) -Xmx (max 堆的最大大小) -Xmn (new 堆的新生代大小)
内存溢出: java.OutOfMemory Error:PermGen space
解决思路: 增加参数:-XX:PrintGCDetails,-XX:+PrintGCTimeStamps和-XX:+PrintGCDateStamps
线程请求的栈深度大于虚拟机所允许的最大深度:java.lang.StackOverflow Error
解决思路: 可以将栈的深度,理解为数组的长度。
控制参数: 1. 加大-Xss(每个线程的堆栈大小)参数。
2. 更换64位虚拟机。
3. 减少线程。
4. 减少最大堆(Xmx)。
java.lang.OutOfMemory Error,有allocate、Native字样
解决思路: 加大本地内存-MaxDirectMemorySize如不指定则与-Xmx一致。
以centos6.8 ,100G的内存,参考配置如下:
JAVA_OPTS="-Xms8g -Xmx8g
-XX:ParallelGCThreads=8
-XX:PermSize=2g
-XX:MaxPermSize=4g
-Xss512k -Xmn6g
-XX:-DisableExplicitGC
-XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled"
CATALINA_OPTS="-Xms8g -Xmx8g
-XX:ParallelGCThreads=8
-XX:PermSize=2g
-XX:MaxPermSize=4g
-Xss512k -Xmn6g
-XX:-DisableExplicitGC
-XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled"
以上是关于四:JVM调优与常见异常处理方案的主要内容,如果未能解决你的问题,请参考以下文章