堆栈溢出(设置栈空间太小,导致栈溢出)
-Xss256k 每个线程堆栈空间太小,导致溢出
-Xss256k这个参数调整了,可能会影响trace的调用。 报如下错误:
Java.lang.StackOverflowError
at net.sf.jsqlparser.util.deparser.ExpressionDeParser.visitBinaryExpression(ExpressionDeParser.java:278)
at net.sf.jsqlparser.util.deparser.ExpressionDeParser.visit(ExpressionDeParser.java:246)
at net.sf.jsqlparser.expression.operators.conditional.OrExpression.accept(OrExpression.java:37)
at net.sf.jsqlparser.util.deparser.ExpressionDeParser.visitBinaryExpression(ExpressionDeParser.java:278)
at net.sf.jsqlparser.util.deparser.ExpressionDeParser.visit(ExpressionDeParser.java:246)
因为这个参数是设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。
问题二:初始化标记阶段耗时过长:
一般的建议是cms阶段两次STW的时间不超过200ms,如果是CMS Initial mark阶段导致的时间过长:
在初始化标记阶段(CMS Initial mark),为了最大限度地减少STW的时间开销,我们可以使用:
-XX:+CMSParallelInitialMarkEnabled
开启初始标记过程中的并行化,进一步提升初始化标记效率;
问题三:remark阶段stw的时间过长
如下图:
可以采用的方式是:
在CMS GC前启动一次ygc,目的在于减少old gen(老年代)对ygc gen(年轻代)的引用,降低remark时的开销—–一般CMS的GC耗时 80%都在remark阶段
-XX:+CMSScavengeBeforeRemark
问题四:
nio框架占用DirectMemory导致的OutOfMemoryError
处理方式:使用XX:+DisableExplicitGC
增加DirectMemory的大小;
1、DirectMemory不属于java堆内存、分配内存其实是调用操作系统的Os:malloc()函数。
2、容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆的最大值(-Xmx指定)一样。注意 ibm jvm默认Direct Memory与-Xmx无直接关系。
3、Direct Memory 内存的使用避免Java堆和Native堆中来回复制数据。从某些场景中提高性能。
4、直接ByteBuffer对象会自动清理本机缓冲区,但这个过程只能作为Java堆GC的一部分来执行,因此它们不会自动响应施加在本机堆上的压力。
5、GC仅在Java堆被填满,以至于无法为堆分配请求提供服务时发生,或者在Java应用程序中显示调用System.gc()函数来释放内存(一些NIO框架就是用这个方法释放占用的DirectMemory)。
6、该区域使用不合理,也是会引起OutOfMemoryError。
7、在需要频繁创建Buffer的场合,由于创建和销毁DirectBuffer的代价比较高昂,是不宜使用DirectBuffer的,但是如果能将DirectBuffer进行复用,那么 ,在读写频繁的情况下,它完全可以大幅改善性能。(对DirectBuffer的读写比普通Buffer快,但是对他的创建和销毁比普通Buffer慢)。
项目中性能调优案例:
oa 系统 针对员工考核 生成一个excel表格,表格里面包含很多的信息,可以理解为大对象,用户请求生成,下载,并且保存一份在redis里面。
问题:访问卡顿
排查过程:优化sql(建索引) 监控cpu 内存(top命令)
访问系统功能很慢,而且时间不固定,通过排查ps jstat full gc 时间很长很长,那就是说明垃圾回收经常发生,系统内存称爆了
大对象放到老年代中,导致老年代内存不够,触发full gc ,触发full gc 会stop the world 而设置jvm 堆内存60g,回收过程很大。
解决方案:
nginx 负载均衡