Java OOM学习

转载自原文:

  1. 什么是java OOM?如何分析及解决oom问题?

什么是OOM?

OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,表现形式就是“java.lang.OutOfMemoryError”。异常。看下官方的说明:

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.
翻译:当内存用完且没有可回收的空间时 抛出这个异常。

为什么会OOM?

为什么会没有内存了?原因不外乎有两点:

  1. 给少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数执行)太少了。
  2. 用多了:应有用的太多,并且用完没有释放,造成内存泄漏或者内存溢出。

内存泄漏

申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄漏了,因为申请者不用了,而又不能被虚拟机分配给别人用。

内存溢出:

申请的内存超过了JVM能提供的内存大小,此时称之为溢出。

在之前没有垃圾自动回收的日子里,比如C语言和C++语言,我们必须亲自负责内存的申请与释放操作,如果申请了内存,用完后又忘记了释放,比如C++中的new了但是没有delete,那么就可能造成内存泄露。偶尔的内存泄露可能不会造成问题,而大量的内存泄露可能会导致内存溢出。

而在Java语言中,由于存在了垃圾自动回收机制,所以,我们一般不用去主动释放不用的对象所占的内存,也就是理论上来说,是不会存在“内存泄露”的。但是,如果编码不当,比如,将某个对象的引用放到了全局的Map中,虽然方法结束了,但是由于垃圾回收器会根据对象的引用情况来回收内存,导致该对象不能被及时的回收。如果该种情况出现次数多了,就会导致内存溢出,比如系统中经常使用的缓存机制。Java中的内存泄露,不同于C++中的忘了delete,往往是逻辑上的原因泄露。

常见的OOM类型

最常见的OOM情况有以下三种:

  • java.lang.OutOfMemoryError: Java heap space :Java堆内存溢出,此种情况最常见,一般由于内存泄漏或者堆的大小设置不当引起。对于内存泄漏,需要通过内存监控软件查找程序中的泄漏代码,而堆大小可以通过虚拟机参数-Xms和我-Xmx等修改。
  • java.lang.OutOfMemoryError:PermGen space:Java永久代溢出,即方法区溢出了,一般出现大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。
  • java.lang.StackOverflowError:不会抛出OOM Error,但也是比较常见的Java内存溢出。Java虚拟机栈溢出,一般是由程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

OOM分析 --- heapdump

  1. 产生DUMP文件:jmap -dump:format=b,file=heap.bin <bin>其中pid可以通过jps获取。
  2. 使用专业分析工具:
  • Mat(eclipse memory analyzer tool),基于eclipse RCP的内存分析工具。
  • jhat:JDK自带的java heap analyze tool,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言OQL,分析相关的应用后,可以通过http://localhost:7000来访问分析结果。不推荐使用,因为在实际的排查过程中,一般是先在生产环境dump出文件来,然后拉到自己的开发机器上分析,所以,不如采用高级的分析工具比如前面的mat来的高效。

这个链接:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html中提供了一个采用mat分析的例子

注意:因为JVM规范没有对dump出的文件的格式进行定义,所以不同的虚拟机产生的dump文件并不是一样的。在分析时,需要针对不同的虚拟机的输出采用不同的分析工具(当然,有的工具可以兼容多个虚拟机的格式)。IBM HeapAnalyzer也是分析heap的一个常用的工具。

小结

涉及到的虚拟机的技术或者工具,往往需要考虑到虚拟机规范以及不同的虚拟机实现。尤其是针对虚拟机调优时,往往需要针对虚拟机在某些方面的实现策略来考虑,比如,不同的虚拟机的垃圾回收算法是不一样的,而这直接影响了虚拟机某些参数的设置,以达到虚拟机的最佳性能。

而针对JVM运行时的分析与诊断,则需要掌握分析基本方法,针对具体情况,运用虚拟机的原理,具体分析。一句话,水很深啊。

原文地址:https://www.cnblogs.com/boothsun/p/8672436.html

时间: 2024-10-03 15:48:12

Java OOM学习的相关文章

java虚拟机学习-触摸java常量池(13)

java虚拟机学习-深入理解JVM(1) java虚拟机学习-慢慢琢磨JVM(2) java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制 java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3) java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4) java虚拟机学习-JVM调优总结(5) java虚拟机学习-JVM调优总结(6) java虚拟机学习-JVM调优总结-基本垃圾回收算法(7) java虚拟机学习-JVM调优总结-垃圾回收面临的

Java基础学习——数组初识(1)

Java基础学习--数组初识(1) 1什么是数组 Java中常见的一种数据结构就是数组,数组可以分为一维数组.二维数组和多维数组. 数组是由一组相同的变量组成的数据类型,数组中每个元素具有相同的数据类型,数组中的每个元素都可以用一个统一的数组名和下标来确定. 2 数组的使用 数组的一般使用步骤: 声明数组 分配内存给该数组 下面是一维数组为例: 数据类型  数组名 []: 数组名 = new 数据类型 [数据个数]: 2.1一维数组的声明与赋值 1.数组的声明 int  num [];    

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

Java并发学习之五——线程的睡眠和恢复

本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.Thread类的sleep方法,可以使线程睡眠.此方法接收一个整数作为参数,表示线程暂停运行的毫秒数.在调用sleep方法后,当时间结束时,JVM会安排他们CPU时间,线程会继续按指令执行. 另一种可能是使用一个有TimeUnit列举元素的sleep方法,使用线程类的sleep方法让当前线程睡眠,但是它接收的参数单位后会转成毫秒的. 2.当你调用sleep()方法,Thread离开CPU并在一段时间内停止运行.在这段时间内,他是不消耗CP

Java EE学习--Quartz基本用法

新浪博客完全不适合写技术类文章.本来是想找一个技术性的博客发发自己最近学的东西,发现博客园起源于咱江苏,一个非常质朴的网站,行,咱要养成好习惯,以后没事多总结总结经验吧.很多时候都在网上搜索别人的总结,我自己也总结些东西,或许多多少少能帮得上别人. 首先提到的是Quartz,一个开源的定期执行计划任务的框架.其实我内心好奇这个框架很久了,像那些能定时修改数据库数据,定时分配任务的功能一直觉得很神奇.心动不如行动,今天我就小小的学习了一下用法,力求言简意赅,大家都懂的我就不说了. 第一步:下载Qu

java nio学习笔记(一)

位置保留,待用 java nio学习笔记(一),布布扣,bubuko.com

JAVA基础学习笔记(2)

看了几天的视频了,都没时间来写下学习笔记,今天来写下第二次的学习笔记,前几天看的给忘记了,就写最新看到的吧 主要内容:1.类的变量与函数(方法) 2.对象的存储方式 3.新建一个对象及对象的赋值与调用 4.空对象 5.匿名对象 1.类的变量与函数(方法) class Dog      //类名 { String name;  //变量的声明 int age; String color; void bark()   //方法的定义(返回值为空,不带参数) { System.out.println(

java排序学习笔记

前面写了js的排序实现,总得玩玩java的哈. 同样,冒泡.选择.快速(这三个之前实现过也写过文章).堆排序,然后做比较. 主要遇到的难点: - -||想轻松点写个封装计时的逻辑,不想每调用一个排序就要写一个计时代码.想想,还是javascript写起来方便: java的话,我想到的方法是写一个抽象类:抽象出排序方法,实现一个排序计时方法(该方法调用了抽象排序,但在先后排序时加入计时代码[感觉像是aop操作]): 接着所有排序类都继承这个抽象类,并实现排序方法,调用的时候直接调用继承的排序计时方

java密码学学习整理--对称加密(着重描述3des)

1.对称加密要点 对称加密算法的核心是加密和解密操作使用同一套密钥.加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要.因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题. 2.des(参考自:http://baike.baidu.com/view/878529.htm?from_id=210508&type=syn&fromtitle=DES&fr=aladdin) DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位(每组的