前言:
  C/C++的程序员渴望Java的自由, Java程序员期许C/C++的约束. 其实那里都是围城, 外面的人想进来, 里面的人想出去.

背景:
  作为Java程序员, 除了享受垃圾回收机制带来的便利外, 还深受OOM(Out Of Memory)的困惑和折磨. 本文借鉴了<<深入理解 Java虚拟机>>, 并结合了小编自身的经历和读者一起面对OOM的困局如何分析和破解.

准备工作:
  工欲善其事必先利其器, 对java进程的快照分析, 是能够帮助我们迅速的定位出错的原因. 这边我们着重介绍内存分析相关的点.
  借助MAT(Memory Analyzer Tool)来分析内存快照.
  MAT的下载地址:
  http://www.eclipse.org/mat/downloads.php
  eclipse的插件url:
  http://download.eclipse.org/mat/1.4/update-site/
  MAT的展示效果如图所示:

内存快照:
  如何去触发java进程生成内存快照呢?
  1). 设定jvm参数, 使得进程在特定条件下进程内存dump.

1
-XX:+HeapDumpOnOutOfMemoryError

  评注: 设置如下虚拟机参数后, 当java进程因为内存溢出, 就会自动对内存进行Dump, 以便相关人员事后进行分析/解读. 
  该方案非常具有针对性, 在崩溃点分析往往能立马定位问题的所在. 该参数设定方案相当于飞机的黑盒子, 记录了出事前所有信息. 
  当然该方案, 最大的局限性就是不能随时随地进行分析, 那如何破呢?
  2). JMap工具来生成
  JMap的使用命令描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Usage:
  jmap [option] <pid>
    (to connect to running process)
  jmap [option] <executable <core>
    (to connect to a core file)
  jmap [option] [server_id@]<remote server IP or hostname>
    (to connect to remote debug server)
where <option> is one of:
  -dump:<dump-options> to dump java heap in hprof binary format
    dump-options:
    live    dump only live objects; if not specified,
          all objects in the heap are dumped.
    format=b binary format
    file=<file> dump heap to <file>
  Example: jmap -dump:live,format=b,file=heap.bin <pid>

  评注: 挑选了部分选项说明, 重要的是dump的规则
  使用命令如下所示:

1
jmap -dump:format=b,file=xxx.hprof <pid>

OOM的原因分类:
  导致程序出现OOM的因素有多种. 大致我们可以把OOM简单的分为堆溢出(Heap), 栈溢出(Stack), 永久代溢出(常量池/方法区), 直接内存溢出. 
  先来看下java的内存分布
  1). 堆溢出(heap)
  编写如下例程:

1
2
3
4
5
6
public static void main(String[] args) {
  List<byte[]> datas = new ArrayList<byte[]>();
  while true ) {
    datas.add(new byte[1024 1024]);
  }
}

  同时设置虚拟机参数, 使得java进程能够快速生成heapdump.

1
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

  评注: 设置heap的内存限制在20m, Xms/Xmx分别对应heap的初始和最大heap大小.
  产生的异常信息:

  mat进行内存分析

  评注: 从这边能看出, 这边聚集了众多的对象, 占据了99%的内存量.
  2). 栈溢出(stack)
  栈溢出的异常, 还是具有明确的指向性的. 暂略.
  3). 永久代溢出(常量池/方法区)
  <<深入理解 Java虚拟机>>阐述了String.intern()和gclib产生动态代理类的两个例子.
  其错误也很有指向性:

1
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

  这边讲述下, 小编(mumuxinfei)很久之前做的一个项目. 
  当时是机顶盒项目(采用IPanel浏览器, 相当于jvm虚拟机), 采用J2ME规范(java 1.1). 不过当时的机器性能不好, 内存少, 不像现在, 一些移动设备配置开始像PC靠齐了. 
  我把一些初始化数据放在类里声明并定义时, 编译没问题, 但是jvm无论如何也run不起来, 总是出错. 不过我把这些数据放在文件里时, 通过运行时载入, 这样就没问题. 当时的我特别疑惑, 不都是内存吗? 同样的数据, 同样的内存, 这么差别就这么大呢?
  当时的我不理解, 后来知道java的内存结构, 我就明白了. 载入的数据放在Heap中, 而定义的常量是放在PermGen空间中. 而当初的设备限制, IPanel浏览器的默认永久空间大小比较小, 导致我只要把一些数据写到常量中定义, 就运行失败.
  不过蛮荒时代, 总是过去了, 现在的机器配置, 你是不会遇到这么诡异的事了. 日子在一天一天的变好, 过去苦难的日子, 现在的小年轻, 你是不会懂的...
  4). 直接内存溢出
  <<深入理解 Java虚拟机>>讲述了DriectByteBuffer的例子. 当然最直接, 也是最容易遇到的, 还是JNI的使用, 搞Android开发的大拿故意能遇到. 这边也略过不讲.

后记:
  从某种角度来说, <<深入理解 Java虚拟机>>已经把OOM的原因和例子说得非常具体了, 小编难以去超越它, 也不愿简单的复制罗列抄袭之. 简单的描述, 权当作学习笔记了.

Java 性能优化实战记录(3)--JVM OOM的分析和原因追查相关推荐

  1. Java 性能优化实战记录(1)---定位并分析耗cpu最多的线程

    1) jps     列出相关的java进程, 以及对应的pid     也可以使用如下命令来尝试     ps aux | grep java --color 2) top -Hp <pid& ...

  2. Java 性能优化实战记录(2)---句柄泄漏和监控

    前言: Java不存在内存泄漏, 但存在过期引用以及资源泄漏. (个人看法, 请大牛指正) 这边对文件句柄泄漏的场景进行下模拟, 并对此做下简单的分析. 如下代码为模拟一个服务进程, 忽略了句柄关闭, ...

  3. 拉勾教育 | Java 性能优化实战 21 讲

    开篇词 开篇词 | Java 性能优化,是进阶高级架构师的炼金石 你好,我是李国.作为<Java 性能优化与面试 21 讲>这个课程的作者,我先来简单介绍下自己. 我曾任京东金融.陌陌科技 ...

  4. 《java性能优化实战》之编程性能优化

    目录 一.java编程性能优化实战 1.如何使用String.intern 节省内存 2.如何使用字符串的分割方法? 3.ArrayList还是LinkedList?使用不当性能差千倍 4.Strea ...

  5. 【java 性能优化实战】3 工具实践:如何获取代码性能数据?

    首先解答一下上一课时的问题.磁盘的速度这么慢,为什么 Kafka 操作磁盘,吞吐量还能那么高? 这是因为,磁盘之所以慢,主要就是慢在寻道的操作上面.Kafka 官方测试表明,这个寻道时间长达 10ms ...

  6. 【java 性能优化实战】1 理论分析:性能优化,有哪些衡量指标、性能优化的技术手段

    指标是我们衡量很多事物,以及做出行为决策的重要参考.例如在生活中,当你打算买汽车时,会关注很多指标,比如动力性.燃油经济性.制动性.操纵稳定性.平顺性.通过性.排放与噪声等,而这些指标也都有相关的测试 ...

  7. Java 性能优化实战工具实践:如何获取代码性能数据?

    首先解答一下上一课时的问题.磁盘的速度这么慢,为什么 Kafka 操作磁盘,吞吐量还能那么高? 这是因为,磁盘之所以慢,主要就是慢在寻道的操作上面.Kafka 官方测试表明,这个寻道时间长达 10ms ...

  8. 【java 性能优化实战】2 深入剖析:哪些资源,容易成为瓶颈

    在第 1 课时,我们简单介绍了解决性能问题常用的一些切入点.本课时我将从计算机资源层面向你讲解,哪些系统组件容易出现性能瓶颈?以及如何判断该系统组件是否达到了瓶颈? 计算机各个组件之间的速度往往很不均 ...

  9. IO 密集型服务 性能优化实战记录

    背景 项目背景 Feature 服务作为特征服务,产出特征数据供上游业务使用.服务压力:高峰期 API 模块 10wQPS,计算模块 20wQPS.服务本地缓存机制: 计算模块有本地缓存,且命中率较高 ...

最新文章

  1. C语言中二维指针,C语言中怎样区分一维指针和二维指针?
  2. php读取mysql分页查询
  3. Java RMI(远程方法调用) 实例与分析 (转)
  4. Nexus安装及配置
  5. php代码常见的变量缩写,PHP代码简洁之道——变量部分
  6. C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序
  7. 关于互斥锁,条件变量的内核源码解析
  8. 代码Review发现问题
  9. 开源Elasticsearch云托管服务,专享企业级服务
  10. nginx php mysql一些常用命令(windows linux)
  11. 转载:JDBC连接数据库教程,postgreSQL
  12. PyQt5笔记(03) -- 消息框
  13. 支配计算领域44年之后,摩尔定律的下一步该往哪里走?
  14. 美团王兴:24岁创业39岁迎来上市,越对未来有信心,越对当下有耐心
  15. 开源中文关系抽取框架,来自浙大知识引擎实验室
  16. 使用reportlab生成条码
  17. 单片机应用案例大全-900套(保持更新)
  18. pass parameters to view(参数视图)
  19. 简单屏幕录制截屏工具
  20. Protect the self: defense mechanisms in action

热门文章

  1. 【设计模式】模板方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
  2. 【MATLAB】图像导出 ( 导出绘制的图像 | 图像设置 )
  3. 【RecyclerView】 十二、RecyclerView 数据更新 ( 修改单条数据 | 批量修改数据 )
  4. 【计算理论】计算复杂性 ( 证明 非确定性图灵机 与 确定性图灵机 的时间复杂度 之间的指数关系 )
  5. 【Kotlin】Kotlin 单例 ( 懒汉式 与 恶汉式 | Java 单例 | Kotlin 单例 | 对象声明 | 伴生对象 | get 方法 | ? 与 !! 判空 )
  6. 【Android FFMPEG 开发】C++ 回调 Java 方法 模板 ( JavaVM *vm | JNIEnv *env | jobject instance | 引用类型 | 模板代码示例 )
  7. JZ2440驱动开发之环境搭建
  8. Action访问Servlet API的三种方法
  9. 利用angular结合translate为项目实现国际化
  10. [转帖]c++ 面试整理