Java堆分析

n内存溢出(OOM)的原因
nJVM中,有哪些内存区间?
    
线程栈:32位:最大值2G
n堆溢出

n永久区 
nJava栈溢出 
            这里的栈溢出指,在创建线程的时候,需要为线程分配栈空间,这个栈空间是向操作系统请求的,如果操作系统无法给出足够的空间,就会抛出OOM


n直接内存溢出 
ByteBuffer.allocateDirect()无法从操作系统获得足够的空间




直接内存需要GC回收,但是直接内存无法引起GC。直接内存使用满时,无法触发GC

如果堆空间很富余,无法触发GC,直接内存可能就会溢出。如果堆空间触发GC,直接内存可以回收


nMAT使用基础
nMemory AnalyzerMAT






可以马上找到系统中什么类,占用空间最多




浅堆(Shallow Heap)与深堆(Retained Heap)
n浅堆
一个对象结构所占用的内存大小

3int类型以及一个引用类型合计占用内存3*4+4=16个字节。再加上对象头的8个字节,因此String对象占用的空间,即浅堆的大小是16+8=24字节
对象大小按照8字节对齐
浅堆大小和对象的内容无关,只和对象的结构有关
n深堆
一个对象被GC回收后,可以真实释放的内存大小
只能通过对象访问到的(直接或者间接)所有对象的浅堆之和 (支配树)


jdk7后,string结构发生变化,但是向8字节对齐后,浅堆还是24字节







 可以看到,所有的Point实例浅堆和深堆的大小都是16字节。而dLine对象,浅堆为16字节,深堆也是16字节,这是因为dLine对象内的两个点fg没有被设置为null,因此,即使dLine被回收,fg也不会被释放。对象cLine内的引用对象de由于仅在cLine内还存在引用,因此只要cLine被释放,de必然也作为垃圾被回收,即decLine的保留集内,因此cLine的深堆为16*2+16=48字节。

对于aLinebLine对象,由于两者均持有对方的一个点,因此,当aLine被回收时,公共点abLine中依然有引用存在,故不会被回收,点a不在aLine对象的保留集中,因此aLine的深堆大小为16+16=32字节。对象bLineaLine完全一致。


显示入引用(incoming)和出引用(outgoing)
支配树
n使用Visual VM分析堆
njava自带的多功能分析工具,可以用来分析堆Dump
            
            
            

            

            
            
nTomcat OOM分析案例

nTomcat OOM

  Tomcat 在接收大量请求时发生OOM,获取堆Dump文件,进行分析。

n使用MAT打开堆
n分析目的:
找出OOM的原因
推测系统OOM时的状态
出解决这个OOM的方法

            
            
            

            
            
            
            
            
            
n解决方法:
1. OOM由于保存session过多引起,可以考虑增加堆大小
2. 如果应用允许,缩短session的过期时间,使得session可以及时过期,并回收













原文地址:https://www.cnblogs.com/litaiqing/p/4614995.html