OutOfMemory(内存溢出异常OOM)

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. (当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error。)

在《Java虚拟机规范》的规定里,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发OutOfMemoryError异常的可能。

内存溢出和内存泄漏

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

常见的OOM

1.Java.lang.OutOfMemoryError:Java heap space(堆溢出)

​ --如何产生:Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会产生内存溢出异常。

​ --如何解决:首先通过内存映像分析工具(如Eclipse Memory Analyzer和JProfile和Jhat)对Dump出来的堆转储快照进行分析。

​ 第一步:分清楚到底是出现了内存泄漏还是内存溢出。

​ 第二步:如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链,找到泄漏对象是通过怎样的引用路径、与哪些GC Roots相关联,才导致垃圾收集器无法回收它们,根据泄漏对象的类型信息以及它到GC Roots引用链的信息,一般可以比较准确地定位到这些对象创建的位置,进而找出产生内存泄漏的代码的具体位置。

​ 第三步:如果不是内存泄漏,换句话说就是内存中的对象确实都是必须存活的,那就应当检查Java虚拟机的堆参数(-Xmx与-Xms)设置,与机器的内存对比,看看是否还有向上调整的空间。再从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行期的内存消耗。

​ --导致堆内存泄漏的常见原因:

静态集合类引起的内存泄漏:像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。

当集合Set里面的对象属性被修改后,再调用remove()方法时不起作用。之所以不起作用,是因为对象属性修改后,对象的hashcode就变了,remove的时候就找不到了。

监听器。Listener未删除。

各种连接。比如数据库连接、Socket连接、IO连接等,没有显式close掉。

非静态内部类。非静态内部类会自动生成构造函数,并把外部类作为构造函数的参数,这样才能在内部类里使用外部类的属性和方法。但是这样内部类会保留外部类的引用,如果内部类与外部类的生命周期不一致,就可能回收不了。

单例模式。在单例对象中引用了其它对象,被引用对象永远不会回收。

2.Java.lang.OutOfMemoryError:GC overhead limit exceeded(超出GC)开销限制

​ --如何产生:JDK6新添错误类型,超过98%的时间系统资源在做垃圾回收,却回收了不到2%的堆内存,通常这样的异常伴随着CPU的冲高。通常是由于堆太小或者内存中存在的对象都是不可回收对象。

​ --如何解决: a、查看系统是否有使用大内存的代码或死循环,定位方法与上一个相同。

  b、通过添加JVM配置,来限制使用内存: < jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg>

3.Java.lang.OutOfMemoryError:Direct buffer memory(直接内存溢出)

​ --如何产生:

​ --如何解决:Heap Dump文件不会看到有什么明显的异常情况,如果发现内存溢出后产生的的Dump文件很小,程序又直接或间接使用DirectMemory(典型的间接使用就是NIO),就可以重点检查内存方面原因。

调整-XX:MaxDirectMemorySize= 参数

4.Java.lang.OutOfMemoryError:unable to create new native thread(不能创建新的本地线程)

​ --如何产生:与平台有关,一个应用进程创建多个线程,超过系统承载极限。高并发请求服务器时,经常出现这个错误。

服务器不允许应用进程创建这么多线程,Linux系统默认允许单个进程可以创建的线程数是1024个。

​ --如何解决:降低应用程序创建线程的数量。

​ 修改linux服务器配置,扩大限制。

5.Java.lang.StackOverflowError(栈溢出SOF)

​ --如何产生: 出现无限递归或死循环,局部变量不停地创建,导出栈溢出。

​ --如何解决: 处理的方法是使用jstack输出.out文件,然后分析每个线程栈的运行情况。 可以通过虚拟机参数-Xss来设置栈的大小。

​ 如果是建立过多线程导致的内存溢出,在不能减少线程数量或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。通过“减少内存”的手段来解决内存溢出。

6.Java.lang.OutOfMemoryError: PermGen space/Metaspace(方法区溢出) (JDK1.8引入元空间)

--如何产生: 一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。另外,过多的常量尤其是字符串也会导致方法区溢出。

​ IDEA集成tomcat环境下反复热发布应用也会出现此现象,JVM默认分配的4M运行空间过小,J2EE项目加载的类过多,造成内存溢出。

--如何解决: 可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。 定位方法与上文的1,2相同。

OOM和SOF的区别

在《Java虚拟机规范》中描述了两种异常: 

1)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。 

2)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。 

《Java虚拟机规范》明确允许Java虚拟机实现自行选择是否支持栈的动态扩展,而HotSpot虚拟机的选择是不支持扩展,所以除非在创建线程申请内存时就因无法获得足够内存而出现OutOfMemoryError异常,否则在线程运行时是不会因为扩展而导致内存溢出的,只会因为栈容量无法容纳新的栈帧而导致StackOverflowError异常。

内存OOM快速定位

1.确认是不是内存本身就分配过小:方法:jmap -heap 10765(进程ID)
2.找到最耗内存的对象:方法:jmap -histo:live 10765 | more
3.确认是否是资源耗尽:工具:pstree/netstat查看进程创建的线程数,以及网络连接数,如果资源耗尽,也可能出现OOM。
通过/proc/${PID}/fd,/proc/${PID}/task,可以分别查看句柄详情和线程数。

CPU100%快速定位

1.找到最耗CPU的进程;
执行top -c ,显示进程运行信息列表
键入P (大写p),进程按照CPU使用率排序
2.找到最耗CPU的线程;
top -Hp 10765 ,显示一个进程的线程运行信息列表
键入P (大写p),线程按照CPU使用率排序
3.查看堆栈,定位线程在干嘛,定位对应代码;
将线程PID转化为16进制。
jstack 10765 | grep '0x2a34' -C5 --color,打印进程堆栈通过线程id,过滤得到线程堆栈

面经中有关OOM的问题

内存溢出有哪些异常,有哪些oom,什么样的oom
JVM内存模型、OOM怎么解决
什么时候会抛栈的OOM
知道什么OOM
内存区域哪些会产生OOM,OOM场景
JVM,内存布局,垃圾回收,OOM怎么排查
oom(out of memory)可能原因
OOM排查思路
JVM,哪里会有OOM问题,OOM和SOF的区别
JVM有哪些垃圾回收器,讲一下细节;JVM有哪些优化配置参数;发生OOM如何定位到具体代码;
tomcat的oom怎么解决?
在什么地方会发生OOM?
如何分析OOM发生的原因?
让你自己实现OOM,你会怎么做?

OutOfMemory相关问题(内存溢出异常OOM)的更多相关文章

  1. 【JVM】TroubleShooting之内存溢出异常(OOM)与调优

    1. OOM概述 If your application's execution time becomes longer and longer, or if the operating system ...

  2. OutOfMemoryError/OOM/内存溢出异常实例分析--虚拟机栈和本地方法栈溢出

    关于虚拟机栈和本地方法栈,在JVM规范中描述了两种异常: 1.如果线程请求的栈深度大于JVM所允许的深度,将抛出StackOverflowError异常: 2.如果虚拟机在扩展栈时无法申请到足够的内存 ...

  3. spark(oom内存溢出异常(out of memory))介绍1

    建立如图maven工程 maven的pom文件内容参考别的随笔 参考pom文件内容 同时记得添加scala oom内存溢出异常(out of memory)

  4. OutOfMemoryError/OOM/内存溢出异常实例分析--堆内存溢出

    Java堆内存溢出 只要不断创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象, 那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常,代码如下: import ...

  5. JVM内存区域与内存溢出异常

    Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...

  6. 《深入理解Java虚拟机》-----第2章 Java内存区域与内存溢出异常

    2.1 概述 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任 ...

  7. Java内存溢出异常(上)

    上一篇文章我们讲了JVM运行时数据区域与内存溢出异常,其中对于内存溢出异常这部分将的不够详细,这篇文章将着重讲解Java内存溢出异常的相关知识.如果有没看过上一篇文章的小伙伴们,请点击Java内存区域 ...

  8. Java内存溢出异常(下)

    此篇是上一篇文章Java内存溢出异常(上)的续篇,没有看过的同学,可以先看一下上篇.本篇文章将介绍剩余的两个溢出异常:方法区和运行时常量池溢出. 方法区和运行时常量池溢出 这部分为什么会放在一起呢?在 ...

  9. Java自动内存管理机制学习(一):Java内存区域与内存溢出异常

    备注:本文引用自<深入理解Java虚拟机第二版> 2.1 运行时数据区域 Java虚拟机在执行Java程序的过程中把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创 ...

随机推荐

  1. MySQL索引实践

    数据库索引本质上是一种数据结构(存储结构+算法),目的是为了加快数据检索速度. 1.索引的类型(待完善) 主键索引:给表设置主键,这个表就拥有主键索引. 唯一索引:unique 普通索引:增加某个字段 ...

  2. 01 . Docker原理部署及常用操作命令

    Docker的来源及构造: 容器是一种基础工具:泛指任何用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳,储存,运输物品: 物品可以被放置在容器中,而容器可以保护内容物: 人类使用容器的历史有十 ...

  3. Redis的持久化设计

    Redis 持久化设计 持久化的功能:Redis是内存数据库,数据都是存储在内存中的,为了避免进程退出导致数据的永久丢失,要定期将Redis中的数据以某种形式从内存保存到硬盘,当下次Reids重启时, ...

  4. Tensorflow从0到1(4)之神经网络

    一维数据集上的神经网络 # 1 引入包,创建会话 import tensorflow as tf import numpy as np sess = tf.Session() # 2 初始化数据 da ...

  5. 《ElasticSearch入门》一篇管够,持续更新

    一.顾名思义: Elastic:灵活的:Search:搜索引擎 二.官方简介: Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTf ...

  6. 十六进制颜色码及其表示-(6 digit color code)

    我们知道对于RGB颜色系统,颜色是由三个256位的十进制数值表示的: (R:0-255,G:0-255,B:0-255) 那么一个三元组可以确定一种颜色. 然而,在很多配置文件中颜色并不是直接用十进制 ...

  7. cb31a_c++_STL_算法_查找算法_(4)find_first_of

    cb31a_c++_STL_算法_查找算法_(4)find_first_offind_first_of(b,e,sb,se),sb,second begin, se,second end();find ...

  8. Bestcoder Round8

    4989Summary 既然用C++了就偷懒直接用STL大法了 #include<iostream> #include<algorithm> #include<vecto ...

  9. WeChair项目Alpha冲刺(10/10)

    团队项目进行情况 1.昨日进展    Alpha冲刺第十天 昨日进展: 前端:安排页面美化,设计实名认证 后端:更新dao层代码 数据库:修改数据表属性,与后端部署数据库交互 2.今日安排 前端:继续 ...

  10. vue cli3项目中使用qrcodejs2生成二维码

    组件的形式创建 1.下载依赖 npm install qrcodejs2 2.创建一个.vue的组件放置代码(我创建的是qrcodejs2.vue) //template中的代码 <templa ...