通常,内存的问题就是 GC 的问题,因为 Java 的内存由 GC 管理。有2种情况,一种是内存溢出了,一种是内存没有溢出,但 GC 不健康。

内存溢出的情况可以通过加上

-XX:+HeapDumpOnOutOfMemoryError,该参数作用是:在程序内存溢出时输出 dump 文件。

-XX:HeapDumpPath=/export/Logs/heap_dump_oom.hprof,

有了 dump 文件,就可以通过 dump 分析工具进行分析了,比如常用的MAT,Jprofile,jvisualvm 等工具都可以分析,这些工具都能够看出到底是哪里溢出,哪里创建了大量的对象等等信息。

第二种情况就比较复杂了。GC 的健康问题。

通常一个健康的 GC 是什么状态呢?根据楼主的经验,YGC 5秒一次左右,每次不超过50毫秒,FGC 最好没有,CMS GC 一天一次左右。

而 GC 的优化有2个维度,一是频率,二是时长

我们看YGC,首先看频率,如果 YGC 超过5秒一次,甚至更长,说明系统内存过大,应该缩小容量,如果频率很高,说明 Eden 区过小,可以将 Eden 区增大,但整个新生代的容量应该在堆的 30% - 40%之间,eden,from 和 to 的比例应该在 8:1:1左右,这个比例可根据对象晋升的大小进行调整。

如果 YGC 时间过长呢?YGC 有2个过程,一个是扫描,一个是复制,通常扫描速度很快,复制速度相比而言要慢一些,如果每次都有大量对象要复制,就会将 STW 时间延长,还有一个情况就是 StringTable ,这个数据结构中存储着 String.intern 方法返回的常连池的引用,YGC 每次都会扫描这个数据结构(HashTable),如果这个数据结构很大,且没有经过 FGC,那么也会拉长 STW 时长,还有一种情况就是操作系统的虚拟内存,当 GC 时正巧操作系统正在交换内存,也会拉长 STW 时长。

再来看看FGC,实际上,FGC 我们只能优化频率,无法优化时长,因为这个时长无法控制。如何优化频率呢?

首先,FGC 的原因有几个,

1 是 Old 区内存不够,

2 是元数据区内存不够,

3 是 System.gc(),

4 是 jmap 或者 jcmd,

5 是CMS Promotion failed 或者 concurrent mode failure,

6 JVM 基于悲观策略认为这次 YGC 后 Old 区无法容纳晋升的对象,因此取消 YGC,提前 FGC。

通常优化的点是 Old 区内存不够导致 FGC。如果 FGC 后还有大量对象,说明 Old 区过小,应该扩大 Old 区,如果 FGC 后效果很好,说明 Old 区存在了大量短命的对象,优化的点应该是让这些对象在新生代就被 YGC 掉,通常的做法是增大新生代,如果有大而短命的对象,通过参数设置对象的大小,不要让这些对象进入 Old 区,还需要检查晋升年龄是否过小。如果 YGC 后,有大量对象因为无法进入 Survivor 区从而提前晋升,这时应该增大 Survivor 区,但不宜太大。

上面说的都是优化的思路,我们也需要一些工具知道 GC 的状况。

JDK 提供了很多的工具,比如 jmap ,jcmd 等,oracle 官方推荐使用 jcmd 代替 jmap,因为 jcmd 确实能代替 jmap 很多功能。jmap 可以打印对象的分布信息,可以 dump 文件,注意,jmap 和 jcmd dump 文件的时候会触发 FGC ,使用的时候注意场景。

还有一个比较常用的工具是 jstat,该工具可以查看GC 的详细信息,比如eden ,from,to,old 等区域的内存使用情况。

还有一个工具是 jinfo,该工具可以查看当前 jvm 使用了哪些参数,并且也可以在不停机的情况下修改参数。

包括我们上面说的一些分析 dump 文件的可视化工具,MAT,Jprofile,jvisualvm 等,这些工具可以分析 jmap dump 下来的文件,看看哪个对象使用的内存较多,通常是能够查出问题的。

还有很重要的一点就是,线上环境一定要带上 GC 日志!!!

参考出处: 博客园:http://www.cnblogs.com/stateis0/ 
            个人博客: thinkinjava.cn

内存问题-JVM调优思路的更多相关文章

  1. jvm调优思路及调优案例

    jvm调优思路及调优案例 ​ 我们说jvm调优,其实就是不断测试调整jvm的运行参数,尽可能让对象都在新生代(Eden)里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时 ...

  2. 技能篇:linux服务性能问题排查及jvm调优思路

    只要业务逻辑代码写正确,处理好业务状态在多线程的并发问题,很少会有调优方面的需求.最多就是在性能监控平台发现某些接口的调用耗时偏高,然后再发现某一SQL或第三方接口执行超时之类的.如果你是负责中间件或 ...

  3. JVM调优思路

    一.jvm内存调优 (Gc  和 Full gc) hotspot -Xms40m  最小堆内存 -Xmx512m 最大值内存 -verboose:gc -XX:PrintGCDetails -XX: ...

  4. jvm(3):JVM调优

    typora-root-url: ./ JVM调优思路 目的:减少full GC次数.减少STW时间(一次GC的时间) 手段: 打印GC日志-XX:+PrintGCDetails -XX:+Print ...

  5. 深入理解JAVA虚拟机(内存模型+GC算法+JVM调优)

    目录 1.Java虚拟机内存模型 1.1 程序计数器 1.2 Java虚拟机栈 局部变量 1.3 本地方法栈 1.4 Java堆 1.5 方法区(永久区.元空间) 附图 2.JVM内存分配参数 2.1 ...

  6. java内存管理之垃圾回收及JVM调优

    GC(garbage Collector 垃圾收集器)作用:a.内存的动态分配:b.垃圾回收注:Java所承诺的自动内存管理主要是针对对象内存的回收和对象内存的分配. 一.垃圾标记 程序计数器.Jav ...

  7. JVM 调优 内存调优 CPU 使用调优 锁竞争调优 I/O 调优

    Twitter 工程师谈 JVM 调优 2016年03月24日 10:22:30 wenniuwuren https://blog.csdn.net/wenniuwuren/article/detai ...

  8. 堆内存动态分配情况和jvm调优方向

    由上图可以看出: 堆中分为新生代(占堆1/3内存)和老年代(占堆2/3内存), 新生代又分为Eden区(占新生代内存的8/10)和survivor区(占新生代内存的2/10), survivor区又分 ...

  9. JVM调优的几种策略

    一.JVM内存模型及垃圾收集算法  1.根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) 永久代(Perm) 其中New和Tenured属于堆内存,堆内存会从J ...

随机推荐

  1. web前端页面设计小笔记

    input总是在点击的时候出现蓝色边框,这是input的默认属性,就算设置了border:none:也没有用! #解决方法:outline:none; 设置input框里的placeholder值得字 ...

  2. 应届生第一次Java面试问题分享

    1.  Java四大域 ServletContext域(Application域): 整个WEB应用 HttpSession域(Session域):一次会话 ServletRequest域(Reque ...

  3. servlet之ServletRequest与ServletResponse (三)

    ·servlet的service()方法用于应答请求:每次请求都会调用service()方法 public void service(ServletRequest arg0, ServletRespo ...

  4. Vue开发爬坑记录

    1.使用eslint代码检查时,常见的的错误: 1.1 Expected indentation of 0 spaces but found 1 前面的空格个数不对.应该不能有空格. 1.2 Stri ...

  5. ckeditor_配置 修改工具栏段落的标签和在文中的格式

    在默认的工具栏中自带一个格式的选项,可以编辑文字的段落属性,将文字转换为标题.ckeditor中提供了方法可以对这个标签进行修改. 正在做的项目中不叫标题1标题2,叫章.节.条... . 需要进行配置 ...

  6. Linux matlab.desktop文件

    matlab建立菜单文件老是闪退,须用 matlab -desktop 完整配置 matlab.desktop [Desktop Entry] Name=MATLAB Exec=/usr/local/ ...

  7. Java中对Array数组的常用操作

    目录: 声明数组: 初始化数组: 查看数组长度: 遍历数组: int数组转成string数组: 从array中创建arraylist: 数组中是否包含某一个值: 将数组转成set集合: 将数组转成li ...

  8. Java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind异常

    端口被占用,可能是其他程序占用,也有可能是自己代码逻辑不对,比如BZ在写SocketServer时把添加端口的代码放进了while里(sasasa.....). 查看本机端口是否被占用:netstat ...

  9. JPA、Hibernate框架、通用mapper

    JPA是描述对象-关系表的映射关系,将运行期实体对象持久化到数据库中,提出以面向对象方式操作数据库的思想. Hibernate框架核心思想是ORM-实现自动的关系映射.缺点:由于关联操作提出Hql语法 ...

  10. laravel seed填充数据步骤