java性能分析-堆内存最佳实践-堆分析
堆内存最佳实践
优化垃圾回收器标志参数很重要但是采用更好的编程实践获得更大的性能提升
1.谨慎的创建对象并尽快的丢弃,是更好的内存是提高gc更好的方法
2.频繁创建某种类型的对象会导致整体的性能变差
对象复用设计
线程局部变量
每个线程中创建一个局部变量的副本提供每个线程的单独使用而不会出现线程共享问题
特殊对象应用
java特殊对象引用比如本地引用绑定jni设计
在程序运行时保持对特定对象的引用,而无需考虑该对象是否被回收
对象池
初始化对象池:一定数量的实例
对象池申请使用:线程获取对象
返回对象实例:使用完毕之后返回对象池
清理对象:防止对象池中存储过多无用的对象,需定期清理无用对象
通过对象的状态机控制对象的状态
堆分析
GC工具会通过强制FullGC实现数据的获取,而不会获得下次FullGC的相关信息
堆直方图 heap histogram
jcmd 139382 GC.class_histogram #只输出活跃的对象,该命令会强制执行FullGC -all会显示所有对象
num #instances #bytes class name
1: 111054 35515776 [B
2: 90189 10198200 [C
3: 101302 2431248 com.sleepycat.je.tree.LN
4: 89023 2136552 java.lang.String
5: 18140 2030832 java.lang.Class
6: 15560 1644088 [Ljava.lang.Object;
7: 42125 1348000 java.util.concurrent.ConcurrentHashMap$Node
显示直方图的其他命令
jmap -histo:live 139382 | more
堆转储
jcmd process_id GC.heap_dump /path/to/heap_dump.hprof
jcmd process_id GC.heap_dump /path/to/heap_dump.hprof
执行命令会强制执行Full GC
自动转储GC标志
-XX:+HeapDumpOnOutOfMemoryError 默认关闭
-XX:HeapDumpPath=
-XX:HeapDumpAfterFullGC
-XX:HeapDumpBeforeFullGC
对象的浅大小,保留大小和深大小
浅大小:
指对象本身的大小。如果一个对象包含指向另一个对象的引用,那么浅大小包含引用所占4-8个字节,不包含目标对象的大小
深大小:
包含所引用对象的大小。
深大小和保留大小的区别在于其引用的对象是否是共享的。
内存溢出错误 JVM out-of-memory
jvm没有可用的原生内存
元空间内存不足
java堆本身内存不足,对于既定大小堆则无法创建额外的对象
jvm花了太多时间执行GC
原生内存溢出
线程栈的原生内存耗尽异常日志
Exception in thread “main” java.lang.OutOfMemoryError:
unable to create new native thread
也可能是操作系统ulimit -u限制数量超出后异常
元空间内存溢出
Exception in thread “main” java.lang.OutOfMemoryError: Metaspace
jvm元空间的原生内存耗尽,元空间默认是不限制大小。
1.如果设置了大小可能会出现元空间原生内存溢出
2.设计到类加载器的内存泄漏,发生在动态加载类的服务中
堆内存溢出
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
jvm不会退出,异常只影响了单个线程,该线程的线程处理器会输出栈轨迹,然后该线程会退出
如果希望JVM在堆内存溢出后退出使用
-XX:+ExitOnOutOfMemoryError 默认关闭
达到GC开销限制
Exception in thread “main” java.lang.OutOfMemoryError: GC overhead limit exceeded
在FullGC中花费时间超过了-XX:GCTimeLimit=N的值,默认98
在FullGC中内存量少于-XX:GCTimeLimit=N的值。默认2