转载:https://blog.csdn.net/xuqu_volition/article/details/53786096

引言

本文仅关注一些常见的虚拟机内存监视手段,以及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:Java heap 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总结-内存监视手段及各区域内存溢出解决的更多相关文章

  1. JVM内存监视手段和内存溢出解决方案

    引言 本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个部分内存溢出的发生和对应的解决方案,总体来说属于概括性总结,涉及相对不是很深入,目的是让自己和其它初学者有一个框架性.概念性的了 ...

  2. 初始jvm(一)---jvm内存区域与溢出

    jvm内存区域与溢出 为什么学习jvm 木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时候,那么就需要你对jvm的了解掌握. 当一个系统出现内存溢出,内存泄露的时候,因为你懂jv ...

  3. JVM学习总结(一):Java内存区域

    一.JVM运行时数据区 1.程序计数器: (1)一块较小的线程私有的内存空间. (2)JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(或一个内核) ...

  4. jvm系列 (一) ---jvm内存区域与溢出

    jvm内存区域与溢出 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 为什么学习jvm 木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时 ...

  5. 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)

    欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...

  6. JVM性能优化系列-(2) 垃圾收集器与内存分配策略

    2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...

  7. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  8. JVM学习笔记三:垃圾收集器与内存分配策略

    内存回收与分配重点关注的是堆内存和方法区内存(程序计数器占用小,虚拟机栈和本地方法栈随线程有相同的生命周期). 一.判断对象是否存活? 1. 引用计数算法 优势:实现简单,效率高. 致命缺陷:无法解决 ...

  9. Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)

    勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行 ...

随机推荐

  1. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

  2. BZOJ 2118 墨墨的等式(最短路)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2118 [题目大意] 求a1x1+a2y2+…+anxn=B在B的取值范围,有多少B可以 ...

  3. KMP 解决串的模式匹配问题

    初学KMP的时候,一直不得要领.后来学习AC自动机的时候,一下子明白了KMP实际上是AC自动机的特殊情况. 首先贴三段代码,一组是回溯法,暴力求解,另外两个是KMP串模式匹配 /* 回溯法字符串匹配算 ...

  4. bzoj 3252: 攻略 -- 长链剖分+贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Description 题目简述:树版[k取方格数]   众所周知,桂木桂马是攻略之神,开启攻略之神 ...

  5. [Cocos2dx] CCCamera照相机 详解

    前言 在3D游戏当中,我们经常会使用到照相机这个东西,无论你使用的是哪一款引擎,都会用到,同时,照相机这个东西涉及到的东西比较多,基础知识需要扎实一些才可以. 如何使用 很久之前做项目的时候用到过一次 ...

  6. Loj10153 二叉苹果树

    题目描述 有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点.这棵树共 NN 个节点,标号 11 至 NN,树根编号一定为 11. 我们用一根树枝两端连接的节点编号描述一根树枝的 ...

  7. w​x​F​o​r​m​B​u​i​l​d​e​r​初​体​验

    第一步 打开wxFormBuilder 修改工程信息并保存工程 Name: 工程名 File: 生成代码(.py)文件名 Code_generation: 生成代码类型 第二步 创建窗体 切换至for ...

  8. trigger、procedure和event如何同步

    最近遇到一个需求涉及存储过程,被突然问题到如何同步问题问到了,赶紧补课学习一下. 首先,先看一下trigger.procedure和event的定义都是什么? trigger: 触发器是一个被指定关联 ...

  9. windows组策略和共享

    Author: Jin Date: 20140585 ENV: win2008 R2 5年没弄windows了,现在随便弄弄,说实话不太喜欢windows,不出问题时候很方便,一出问题很头大.所有东西 ...

  10. IIS Express并发数设置

    今天将之前的一个瓦片图的服务迁移到了asp.net core试了一下,使用的时候感觉客户端刷新时有些慢,估计是并发连接数限制的原因. 由于这是一个开发中的版本,是用IIS Express部署的,IIS ...