JVM内存监视手段和内存溢出解决方案
引言
本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个部分内存溢出的发生和对应的解决方案,总体来说属于概括性总结,涉及相对不是很深入,目的是让自己和其它初学者有一个框架性、概念性的了解,当遇到问题时有迹可循、不至于不知所措。
一、虚拟机内存监视手段
虚拟机常出现的问题包括:内存泄露、内存溢出、频繁GC导致性能下降等,导致这些问题的原因可以通过下面虚拟机内存监视手段来进行分析,具体实施时可能需要灵活选择,同时借助两种甚至更多的手段来共同分析。
比如GC日志可以分析出哪些GC较为频繁导致性能下降、是否发生内存泄露。jstat工具和GC日志类似,同样可以查看GC情况、分析是否发生内存泄露。判断发生内存泄露后,可以通过jmap工具和MAT等分析工具的结合查看虚拟机内存快照,分析发生内存泄露的原因。内存溢出快照可以分析出内存溢出发生的原因等。
GC日志记录
将JVM每次进行GC的情况记录下来,通过观察GC日志可以看出来GC的频度、以及每次GC都回收了哪些区域的内存,根据这些信息为依据来调整JVM相关设置,可以减少Minor GC的频率以及Full GC的次数,还可以判断是否有内存泄露发生。
下面是常见的GC日志输出参数:
u -verbose.gc:显示GC的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。
u -XX:+printGCdetails:详细了解GC中的变化。
u -XX:+PrintGCTimeStamps:了解垃圾收集发生的时间,自JVM启动以后以秒计量。
u -XX:+PrintHeapAtGC:了解堆的更详细的信息。
u -Xloggc:[file]:将GC信息输出到单独的文件中
jstat:虚拟机统计信息监控工具
实时监视虚拟机运行时的类装载情况、各部分内存占用情况、GC情况、JIT编译情况等。
例:每隔250ms查询一次进程2211的垃圾收集情况,查询50次
步骤①:jps列出本机所有运行的jvm实例,获取jvm的pid
步骤②:jstat实时监控gc情况,jstat –gc 2211 250 50
其他参数包括:
-class监视类装载、卸载数量、总空间以及类装载所耗费时间
-gccapacity监视内容与-gc相同,输出主要关注堆各个区域用到的最大、最小空间
-gcutil监视内同与-gc相同,输出主要关注堆各个区域已使用空间所占总空间百分比
-gcnew监视新生代GC情况
-gcold监视旧生代GC情况
jmap:虚拟机内存映像工具
jmap工具可以让运行中的JVM生成Dump文件,当JVM内存出现问题时可以通过jmap生成快照,分析整个堆,主要经历两个步骤:
步骤1:jps列出本机所有运行的jvm实例,获取jvm的pid
步骤2:使用jmap命令将指定JVM快照导出为dump文件
jmap -dump:format=b,file=path/heap.bin PID
获得JVM快照的dump文件之后,可以通过MAT工具进行分析。
MAT(MemoryAnalyzer Tool)工具是eclipse的一个插件,使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GC Roots的相关信息,最吸引人的是能够快速为开发人员生成内存泄露报表,方便定位和分析问题。
除此之外,jmap还可以查询finalize执行队列、Java堆和持久代的详细信息,比如空间使用率,当前使用的是哪种收集器等。
内存溢出快照生成
通过设置JVM参数,可以让虚拟机发生OutOfMemoryError(OOM)内存溢出时自动生成dump文件,通过分析dump文件查看内存使用情况可以找到内存溢出发生的原因:
-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/path/to/heap/dump
获得JVM快照的dump文件之后,可以通过MAT工具进行分析。
二、运行时数据区内存溢出
JVM运行时数据区分为以下几个部分:
其中方法区和堆是所有工作线程共享的,而栈、程序计数器和本地方法栈是线程私有的。
注:图片转自网络
1.程序计数器
作用:指向当前线程下一条需要执行的字节码指令的地址
内存溢出:不会发生
2.虚拟机栈
作用:由栈帧组成、每个栈帧代表一次方法调用,其包含存储变量表、操作数栈和方法出口三个部分,方法执行完成后该栈帧将被弹出。
内存溢出:StackOverflowError和OutOfMemoryError。
溢出原因:
StackOverflowError:如果请求的栈的深度大于虚拟机所允许的深度,将会抛出这个异常,如果使用虚拟机默认参数,一般达到1000到2000这样的深度没有问题。
OutOfMemoryError:因为除掉堆内存和方法区容量,剩下的内存由虚拟机栈和本地方法栈瓜分,如果剩下的内存不足以满足更多的工作线程的运行、或者不足以拓展虚拟机栈的时候,就会抛出OutOfMemoryError异常。
解决方法:
针对StackOverflowError:
1. 首先栈溢出会输出异常信息,根据信息查看对应的方法调用是否出现无限调用、或者栈帧过大等代码逻辑上的问题,通过修改代码逻辑解决;
2. 如果确确实实需要更大的栈容量,可以检查并调大栈容量:-Xss16m。
针对OutOfMemoryError:
1. 首先检查是否创建过多的线程,减少线程数
2. 可以通过“减少最大堆容量”或“减少栈容量”来解决。
3.本地方法栈
作用:与虚拟机栈唯一的不同是虚拟机栈执行的是java方法,而本地方法栈执行的是本地的C/C++方法
内存溢出:StackOverflowError和OutOfMemoryError
溢出原因:同虚拟机栈
解决方法:同虚拟机栈
4.堆
作用:所有线程共享,存放对象实例
内存溢出:OutOfMemoryError:Javaheap space
溢出原因:堆中没有足够内存完成实例分配,并且无法继续拓展时
解决方法:
1.内存泄露检查:首先通过“内存溢出快照 + MAT等分析工具”,分析是否存在内存泄露现象,检查时可以怀疑的点比如集合、第三方库如数据库连接的使用、new关键字相关等。
2.如果没有内存泄露,那么就是内存溢出,所有对象却是都还需要存活,这个时候就只能调大堆内存了:-Xms和-Xmx。
5.方法区
作用:所有线程共享,存放已加载的class信息、常量、静态变量和即时编译后的代码
内存溢出:OutOfMemoryError:PermGen space
溢出原因:方法区没有足够内存完成内存分配存放运行时新加载的class信息
解决方法:
1. 内存泄露检查:检查是否加载过多class文件(jar文件),或者重复加载相同的class文件(jar文件)多次
2. 通过-XX:PermSize=64M -XX:MaxPermSize=128M改大方法区大小
6.运行时常量池
作用:方法区的一部分,存放常量
内存溢出:OutOfMemoryError:PermGen space
溢出原因:方法区没有足够的内存完成内存分配,存放运行时新创建的常量,比如String类的intern()方法,其作用是如果常量池已经包含一个相同的字符串,则返回其引用,否则将此String对象包含的字符串添加到常量池中。
解决方法:
1. 内存泄露检查:检查是否创建过多常量
2. 通过-XX:PermSize=64M -XX:MaxPermSize=128M改大方法区大小
7.直接内存
作用:不属于JVM运行时数据区,也不是虚拟机规范中定义的内存区域,JDK1.4引入的NIO中包含通道Channel和缓冲区Buffer,应用程序从通道获取数据是先经过OS的内核缓冲区,再拷贝至Buffer,因为比较耗时,所以Buffer提供了一种直接操作操作系统缓冲区的方式,即ByteBuffer.allocateDirector(size),这个方法返回DirectByteBuffer应用就是指向这个底层存储空间关联的缓冲区,即直接内存(native memory),或者叫堆外内存。
内存溢出:OutOfMemoryError
溢出原因:JVM所需内存 + 直接内存 > 机器物理内存(或操作系统级限制),无法动态拓展
判断方法:内存泄露检查:例如内存占用较高,机器性能骤降,但是通过GC信息或者jstat发现GC很少,通过jmap获得快照分析后也没发现什么异常,而程序中又直接或者间接地用到了NIO,那么和可能就是直接内存泄露了。
解决方法:分析NIO相关的程序逻辑解决。
JVM内存监视手段和内存溢出解决方案的更多相关文章
- JVM总结-内存监视手段及各区域内存溢出解决
转载:https://blog.csdn.net/xuqu_volition/article/details/53786096 引言 本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个 ...
- 应用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap space)
http://www.educity.cn/wenda/351088.html 使用jacob组件造成的内存溢出解决方案(java.lang.OutOfMemoryError: Java heap s ...
- 牛客网Java刷题知识点之内存溢出和内存泄漏的概念、区别、内存泄露产生原因、内存溢出产生原因、内存泄露解决方案、内存溢出解决方案
不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 ...
- PHP内存溢出解决方案
一.内存溢出解决方案 在做数据统计分析时,经常会遇到大数组,可能会发生内存溢出,这里分享一下我的解决方案.还是用例子来说明这个问题,如下: 假定日志中存放的记录数为500000条,那么解决方案如下: ...
- Android内存溢出解决方案(OOM)
众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视平台而定).因此在开发应用时需要特别关注自身的内存使用量,而一般最耗内存量的资源,一般是图片.音频文 ...
- JVM探秘:MAT分析内存溢出
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. MAT是分析Java堆内存的一个工具,全称是 The Eclipse Memory A ...
- 配置Tomcat的JVM的大小解决Tomcat内存溢出的问题
操作步骤如下图所示(图中也有对应的文字说明已比较详细,不再用文字做过多的解释): 1: 2: 3: 4: 5: 下面是配置的参数的说明: -Xms256m JV ...
- Webpack编译提示内存溢出解决方案
在项目开发中,随着业务需求的复杂项目随之增大,再加上同一个文件被引用次数过于频繁在开发编译或者上线打包时经常会出现如下错误: 这个报错的意思就是Node内存不足所导致的,我们都知道 Node 是基于V ...
- 深入理解JVM虚拟机11:Java内存异常原理与实践
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...
随机推荐
- Python Django 前后端数据交互 之 前端向后端发送数据
Python Django 之 前端向后端发送数据
- DevExpress v17.2新版亮点——CodeRush篇(三)
用户界面套包DevExpress v17.2日前终于正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了CodeRush v17.2 的新功能,快来下载试用新版本! 代码格式和清理 文档 ...
- Java Socket 实现HTTP服务器核心
原文链接:http://www.ihuxu.com/p/235.html 首先了解下HTTP协议: wikiPedia的说明很好,在此不重复了.链接:http://zh.wikipedia.org ...
- L233
Betty was offended because she felt that her friends had ignored her purposefully(deliberately) at t ...
- L210 Ebola
Progress in fighting Democratic Republic of the Congo's Ebola outbreak, the second worst ever, will ...
- PHP出现Cannot modify header information问题的解决方法
在C盘的WINDOWS中找到php.ini 这个配置文件,然后查找一项:output_buffering将其值由原来的off改为on,重新启动Apache就ok了.
- CODE大全大量Flash网站收藏
我的博客:CODE大全:www.codedq.net:业余草:www.xttblog.com:爱分享:www.ndislwf.com或ifxvn.com. http://www.wallop.com在 ...
- asp.net webform 当前上下文中不存在名称“__o”
错误 CS0103 当前上下文中不存在名称“__o” 最近在搞一个webform项目, 再页面写了点<%%>代码, 结果编译下居然出现了这个错误 炸裂啊, 这是什么毛线, 看起来是 In ...
- torch7 安装 并安装 hdf5模块 torch模块 nn模块 (系统平台为 ubuntu18.04 版本)
今年的CCF A会又要开始投稿了,实验室的师弟还在玩命的加实验,虽然我属于特殊情况是该从靠边站被老板扶正但是实验室的事情我也尽力的去帮助大家,所以师弟在做实验的时候遇到了问题也会来问问我,这次遇到的一 ...
- I.MX6 HUAWEI MU609 3G porting
/*************************************************************************** * I.MX6 HUAWEI MU609 3G ...