36-Java程序员的梦魇:OOM内存溢出!

简介: 作为一名Java程序员,平时在公司拼命加班、任劳任怨干活,好不容易熬夜开发完系统,测试完毕,Bug修复完毕,然后上线部署系统,系统开始正常运行,终于歇口气能好好放松下,喝杯Java压压惊了,But!上线后最害怕的事是什么?

前言:

作为一名Java程序员,平时在公司拼命加班、任劳任怨干活,好不容易熬夜开发完系统,测试完毕,Bug修复完毕,然后上线部署系统,系统开始正常运行,终于歇口气能好好放松下,喝杯Java压压惊了,But!上线后最害怕的事是什么?

不用多说,相信大家应该猜到了,一定是事故!很多大公司叫 Case,一旦当系统出现 Case,比如线上核心系统突然宕机不可用,导致几个小时内用户无法下单,进而导致公司损失几百万,甚至几千万;或者公司的某个单点登录系统突然不可用,导致所有用户无法登录APP,也无法下单;或者公司的缓存集群突然全面故障,进而导致公司的全部系统一起瘫痪!或者因为某个明星的突然出轨,结果导致流量集中访问某台服务器,直接把数据库搞挂!

凡是以上种种,都可以称作为:重大Case!一旦有Case,就会有程序员被拉出去祭天,当然这也是网上常见的一个段子(开个玩笑)。

针对这些事故,肯定是需要有人去承担的,重要的是分析到底什么原因导致的事故,谁的责任,后续如何优化以及避免!

那么作为Java程序员而言,先不考虑自己系统外部依赖的缓存、消息队列、数据库等等东西挂掉,就我们自己系统本身而言,最常见的挂掉原因是什么呢?

答案:没错!就是系统OOM(Out Of Memory),也就是所谓的内存溢出!

为什么会出现OOM?

通过之前JVM的一系列学习,相信大家对于JVM内存结构,内存分配,运行原理已经了解的非常清楚了,那么为什么系统会发生OOM呢?

首先给出官方的一段解释:

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(注:非exception,因为这个问题已经严重到不足以被应用处理)。

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

1)分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。

2)应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。

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

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

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

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

其实简单总结一下Java系统为什么发生OOM:不外乎就是不停的往JVM内存中扔东西,导致最终没有足够的内存可以容纳,如下图所示:

一旦系统不停的往内存中大量塞东西,导致JVM内存撑爆,直接OOM,系统瘫痪,那么对于我们来说是致命的打击,直接导致我们的系统停止运转,甚至JVM进程直接崩溃,进程都没了。用户点击APP,网页都没反应。对于程序员的我们来讲可能辛苦开发了几个月的绩效奖金不但拿不到,反而被扣绩效,甚至年终奖也没了。。。弄不好今年还得提前出去找工作了

如何处理OOM呢?

其实最可怕的并不是线上系统发生OOM,最可怕的是很多工程师压根儿就没有这种处理线上系统故障的经验!

当发生OOM之后,根本不知道系统为什么会突然OOM?到底产生了多少对象,为什么会产生这些对象,到底是哪些对象,内存到底分配了多大,如何去排查这个问题,如何解决,一切皆是迷!

我不听,我不听,这肯定不关我的事儿!一定不是我的代码导致的。这是不是你的内心第一想法?

接下来OpenCoder将为大家带来针对各种可能发生OOM的情况,结合内存溢出的一些场景,通过模拟代码真实感受以及如何解决OOM带来的问题,给到大家如何去监控、定位、排查、分析和解决JVM OOM的问题,再也无惧线上系统突然出现的OOM状况!

目录
相关文章
|
2月前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
39 6
|
27天前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
27 0
|
29天前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
38 8
|
27天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
1月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
55 5
|
29天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
29天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
2月前
|
算法 Java 开发者
Java内存管理与垃圾回收机制深度剖析####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,特别是其垃圾回收机制的工作原理、算法及实践优化策略。不同于传统的摘要概述,本文将以一个虚拟的“城市环卫系统”为比喻,生动形象地揭示Java内存管理的奥秘,旨在帮助开发者更好地理解并调优Java应用的性能。 ####
|
2月前
|
Java
java内存区域
1)栈内存:保存所有的对象名称 2)堆内存:保存每个对象的具体属性 3)全局数据区:保存static类型的属性 4)全局代码区:保存所有的方法定义
24 1
|
26天前
|
存储 监控 算法
Java内存管理的艺术:深入理解垃圾回收机制####
本文将引领读者探索Java虚拟机(JVM)中垃圾回收的奥秘,解析其背后的算法原理,通过实例揭示调优策略,旨在提升Java开发者对内存管理能力的认知,优化应用程序性能。 ####
38 0