JVM-性能调优

内存溢出

内存溢出的原因:程序在申请内存时,没有足够的内存空间。

内存溢出的几种方式:
1.栈溢出:方法死循环递归调用(StackOverflowError)、不断建立线程(OurOfMemoryError)
2.堆溢出:不断创建对象,分配对象大于最大对的大小(OurOfMemoryError)
3.直接内存:分配的本地内存大小大于JVM的限制
4.方法区溢出:在经常动态生产大量Class的应用中,CGLib字节码增强,动态语言,大量JSP,基于OSGi的应用

内存泄漏

程序在申请内存后,无法释放已申请的内存空间

内存泄漏的几种方式:
1.长生命周期的对象持有短生命周期对象的引用:例如将ArrayList设置为静态常量,则容器中的对象在程序结束前是不能被释放,造成内存泄漏。
2.连接未关闭 : 数据库连接、网络链接和IO链接等
3.变量作用域不合理 : 1.一个变量定义的作用范围大于其适用范围。2,没有及时把对象设置为null
4.内部类持有外部类 :非静态内部类创建或持有外部类的引用,默认是强引用,因此,内部类的生命周期长于外部类,很容易内存泄漏
5.Hash值改变 : 集合中修改了对象中的那些参与计算哈希值的字段,会导致无法从集合中单独删除当前对象,造成内存泄漏。

内存泄漏和内存溢出辨析

相同与不同
内存溢出:实实在在的内存空间不足导致
内存泄漏:该释放的对象没有释放,多见于自己使用容器保存原的情况下。

如何避免
内存溢出:检查代码以及设置足够的空间
内存泄漏:一定代码有问题

往往很多情况下,内存溢出就是内存泄漏造成的。

GC调优原则

  1. 大多数的java应用不需要GC调优
  2. 大部分需要GC调优的,不是参数问题,而是代码问题
  3. 在实际项目中,分析GC情况优化代码比调整GC参数要重要
  4. GC调优是最后的手段

目的

  1. GC的时间足够小
  2. GC的次数足够小

调优步骤

  1. 监视GC的状态
  2. 分析结果,判断是否需要优化
  3. 调整GC类型和内存分配
  4. 不断分析和调整
  5. 全面应用参数

逃逸分析

栈上分配
-XX:+DoEscapeAnalysis:启用逃逸分析(默认打开)
-XX:+EliminateAllocations:标量替换(默认打开)
-XX:+UseTLAB 本地线程分配缓冲(默认打开)

如果是逃逸分析出来的对象可以在栈上分配,就不用垃圾回收
没有逃逸分析的对象都在堆上分配(触发频繁GC,加重负担)
JVM-性能调优