本章进入JVM学习的最后一节,此节主要分析的是堆,因为堆是JAVA程序中最常用使用到的地方,因此对这个地方有必要进行下细致的分析特别是OOM,言归正传,进入正文。

一、内存溢出(OOM)的原因

在JVM中,有哪些内存区间?

堆溢出
public static void main(String args[]){
ArrayList<byte[]> list=new ArrayList<byte[]>();
for(int i=0;i<1024;i++){
list.add(new byte[1024*1024]);
}
}

永久区
生成大量的类
public static void main(String[] args) {
for(int i=0;i<100000;i++){
CglibBean bean = new CglibBean("geym.jvm.ch3.perm.bean"+i,new HashMap());
}
}

Java栈溢出

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

public static class SleepThread implements Runnable{
public void run(){
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String args[]){
for(int i=0;i<1000;i++){
new Thread(new SleepThread(),"Thread"+i).start();
System.out.println("Thread"+i+" created");
}
}

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

for(int i=0;i<1024;i++){
ByteBuffer.allocateDirect(1024*1024);
System.out.println(i);
System.gc();
}

二、MAT使用基础

浅堆(Shallow Heap)与深堆(Retained Heap)
显示入引用(incoming)和出引用(outgoing)
支配树

nMemory Analyzer(MAT)
n基于Eclipse的软件
nhttp://www.eclipse.org/mat/
 

                                       

浅堆
一个对象结构所占用的内存大小
 

–3个int类型以及一个引用类型合计占用内存3*4+4=16个字节。再加上对象头的8个字节,因此String对象占用的空间,即浅堆的大小是16+8=24字节
–对象大小按照8字节对齐
–浅堆大小和对象的内容无关,只和对象的结构有关
 深堆

–一个对象被GC回收后,可以真实释放的内存大小
–只能通过对象访问到的(直接或者间接)所有对象的浅堆之和 (支配树)

可以看到,所有的Point实例浅堆和深堆的大小都是16字节。而dLine对象,浅堆为16字节,深堆也是16字节,这是因为dLine对象内的两个点f和g没有被设置为null,因此,即使dLine被回收,f和g也不会被释放。对象cLine内的引用对象d和e由于仅在cLine内还存在引用,因此只要cLine被释放,d和e必然也作为垃圾被回收,即d和e在cLine的保留集内,因此cLine的深堆为16*2+16=48字节。
对于aLine和bLine对象,由于两者均持有对方的一个点,因此,当aLine被回收时,公共点a在bLine中依然有引用存在,故不会被回收,点a不在aLine对象的保留集中,因此aLine的深堆大小为16+16=32字节。对象bLine与aLine完全一致。

三、使用Visual VM分析堆

– java自带的多功能分析工具,可以用来分析堆Dump

类的柱状图 ,显示对象数量,总大小等:

从类试图切换到实例试图,显示所有的实例:

使用OQL查询:

返回引用了(0,0)这个点的所有对象

四、Tomcat OOM分析案例

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

如果是session过多引起OOM

–  OOM由于保存session过多引起,可以考虑增加堆大小

–  如果应用允许,缩短session的过期时间,使得session可以及时过期,并回收

PS:具体的分析逻辑太长,此处不做详细介绍,可以参考附件。

感谢大家的学习,thank you !  后面将进入多线程学习系列,敬请关注。 

参考文献:

葛一鸣《深入JVM内核》视频学习

JVM学习十三:JVM之堆分析的更多相关文章

  1. 深入理解JVM(八)——java堆分析

    上一节介绍了针对JVM的监控工具,包括JPS可以查看当前所有的java进程,jstack查看线程栈可以帮助你分析是否有死锁等情况,jmap可以导出java堆文件在MAT工具上进行分析等等.这些工具都非 ...

  2. JVM学习笔记-JVM模型

    JVM学习笔记 == 标签(空格分隔): jvm 学习笔记全部来自于<深入理解java虚拟机>总结 jvm内存示意图 虚拟机栈(Java Virtual Machine Stacks): ...

  3. jvm学习006 jvm内存结构分配

    主要内容如下: JVM启动流程 JVM基本结构 内存模型 编译和解释运行的概念 一.JVM启动流程: JVM启动时,是由java命令/javaw命令来启动的. 二.JVM基本结构: JVM基本结构图: ...

  4. JVM学习十三 - (复习)HotSpot 虚拟机对象探秘

    对象的内存布局 在 HotSpot 虚拟机中,对象的内存布局分为以下 3 块区域: 对象头(Header) 实例数据(Instance Data) 对齐填充(Padding) 对象头 对象头记录了对象 ...

  5. JVM学习心得—JVM内存模型(个人整理,请勿转载)

    一.运行时数据区域 线程私有的:程序计数器+虚拟机栈+本地方法栈 线程共享的:堆+方法区(运行时常量池)+直接内存(非运行时数据区的一部分) *JDK1.8后将方法区废除,新增元空间. 1.1 程序计 ...

  6. JVM学习目录

    JVM学习目录 JVM的整体结构 1.类加载子系统 类加载子系统 2.运行时数据区 运行时数据区总览 堆.栈.方法区的详细图解 2.1.程序计数器 程序计数器 2.2.本地方法栈 本地方法栈 2.3. ...

  7. JVM学习总结一——内存模型

    JVM是java知识体系的基石之一,任何一个java程序的运行,都要借助于他.或许对于我这种初级程序员而言,工作中很少有必要刻意去关注JVM,然而如果能对这块知识有所了解,就能够更清晰的明白程序的运行 ...

  8. JVM学习--(八)java堆分析

    上一节介绍了针对JVM的监控工具,包括JPS可以查看当前所有的java进程,jstack查看线程栈可以帮助你分析是否有死锁等情况,jmap可以导出java堆文件在MAT工具上进行分析等等.这些工具都非 ...

  9. JVM内核-原理、诊断与优化学习笔记(八):JAVA堆分析

    文章目录 内存溢出(OOM)的原因 在JVM中,有哪些内存区间? 堆溢出 永久区 Java栈溢出 直接内存溢出 小问题? MAT使用基础 柱状图显示 支配树 显示线程信息 显示堆总体信息,比如消耗最大 ...

随机推荐

  1. 记录 C++ STL 中 一些好用的函数--持续更新 (for_each,transform,count_if,find_if)

    在日常的编程中,有这么几种操作还是比较常见的: 把一组数据都赋值成一个数,在一组数据中查找一个数,统计一组数据中符合条件的数等等. 一般的写法可以用循环,没有什么是循环不能搞定的.假如在这里怎么用介绍 ...

  2. 第三次c++作业

    https://github.com/egoistor/3Elevators-scheduling 老实说,因为这周时间紧张,(高数的期中考和一些奇奇怪怪的时期), 所以代码大体是有,但是很多细节处理 ...

  3. CDOJ ABCDE dp(前缀和优化)

    题目链接: http://acm.uestc.edu.cn/#/problem/show/1307 ABCDE Time Limit: 1000/1000MS (Java/Others)Memory ...

  4. Java 异常注意事项

    异常的注意事项:   1,子类在覆盖父类方法时,父类的方法如果抛出了异常, 那么子类的方法只能抛出父类的异常或者该异常的子类.   2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集.     ...

  5. css声明的优先级

    选择器的特殊性 选择器的特殊性由选择器本身的组件确定,特殊性值表述为4个部分,如0,0,0,0,0 一个选择器的具体特殊性如下确定 1.对于选择器给定的ID属性值,加0,1,0,0 2.对于选择器中给 ...

  6. PAT 甲级 1083 List Grades

    https://pintia.cn/problem-sets/994805342720868352/problems/994805383929905152 Given a list of N stud ...

  7. 爬虫学习之-python插入mysql报错

    异常:'latin-1' codec can't encode characters in position 62-66: ordinal not in range(256) 用Python通过pym ...

  8. Additinal Dependencies和#pragma comment(lib,"*.lib")的分析

     网上.一些书上也写道,这两种方式作用一样.其实仔细分析,它们两者还是有非常大的差异的. Additinal Dependencies和#pragma comment(lib,"*.lib& ...

  9. (转)Linux 命令--查看物理CPU个数、核数、逻辑CPU个数

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cpuinfo| ...

  10. HttpWebRequest和HttpWebResponse的应用

    创建使用类HttpHelper: public class Httpparam { public string UserAgent { get; set; } public string Accept ...