前言:
  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.

-XX:+HeapDumpOnOutOfMemoryError	

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

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的规则
  使用命令如下所示:

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

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

public static void main(String[] args) {
  List<byte[]> datas = new ArrayList<byte[]>();
  while ( true ) {
    datas.add(new byte[1024 * 1024]);
  }
}

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

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

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

  mat进行内存分析

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

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 性能优化实战记录(2)---句柄泄漏和监控

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

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

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

  3. JVM——九大工具助你玩转Java性能优化

    本文转载自 http://www.importnew.com/12324.html 本文由 ImportNew - 陈 晓舜 翻译自 idrsolutions.欢迎加入翻译小组.转载请参见文章末尾的要 ...

  4. 《Java性能优化权威指南》

    <Java性能优化权威指南> 基本信息 原书名:Java performance 原出版社: Addison-Wesley Professional 作者: (美)Charlie Hunt ...

  5. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  6. Java性能优化,操作系统内核性能调优,JYM优化,Tomcat调优

    文章目录 Java性能优化 尽量在合适的场合使用单例 尽量避免随意使用静态变量 尽量避免过多过常地创建Java对象 尽量使用final修饰符 尽量使用局部变量 尽量处理好包装类型和基本类型两者的使用场 ...

  7. 我把阿里、腾讯、字节跳动、美团等Android性能优化实战整合成了一个PDF文档

    安卓开发大军浩浩荡荡,经过近十年的发展,Android技术优化日异月新,如今Android 11.0 已经发布,Android系统性能也已经非常流畅,可以在体验上完全媲美iOS. 但是,到了各大厂商手 ...

  8. Java 性能优化之 String 篇

    原文:http://www.ibm.com/developerworks/cn/java/j-lo-optmizestring/ Java 性能优化之 String 篇 String 方法用于文本分析 ...

  9. 读书笔记系列之java性能优化权威指南 一 第一章

    主题:java性能优化权威指南 pdf 版本:英文版 Java Performance Tuning 忽略:(0~24页)Performance+Acknowledge 1.Strategies, A ...

随机推荐

  1. 利用开源框架Volley来下载文本和图片。

    Android Volley是Android平台上很好用的第三方开源网络通信框架.使用简单,功能强大. 下载连接地址:http://download.csdn.net/detail/zhangphil ...

  2. Grunt设置

    Grunt完成对LESS实时编译. 安装 安装grunt需要先安装node.js. 之后需要借助npm来安装grunt-cli,在cmd中npm install -g grunt-cli.(测试gru ...

  3. POJ 2762 tarjan缩点+并查集+度数

    Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15494 ...

  4. tarjan求强联通分量 模板

    void tarjan(int u) { dfn[u]=low[u]=++dfs_clock; stack_push(u); for (int c=head[u];c;c=nxt[c]) { int ...

  5. javascript photo1

  6. Hello Struts2

    Struts2 概述 Struts2 是一个用来开发 MVC 应用程序的框架. 它提供了 Web 应用程序开发过程中的一些常见问题的解决方案: 对来自用户的输入数据进行合法性验证; 统一的布局; 可扩 ...

  7. Rhel6-集群管理(luci&&ricci)配置文档

    理论基础: User → HA →     Lb    → web → sql → 分布式filesystem ->磁盘I/O 用户   高可用 负载均衡    应用   数据库      mf ...

  8. 踏着前人的脚印学Hadoop——RPC源码

    A simple RPC mechanism.A protocol  is a Java interface.  All parameters and return types must be one ...

  9. RPI学习--环境搭建_默认启动桌面/终端修改

    参见:http://elinux.org/RPi_raspi-config 首次运行Raspbian会自动进入设置,往后也可以重新进入设置: $ sudo raspi-config 选项3 Enabl ...

  10. 自定义圆的半径layout

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:too ...