JVM 堆、栈概述 与 常见 OOM 原因及解决方案
目录
Java 栈(Stack)
Java 堆(Heap)
堆 (Heap) VS 栈 (Stack)
常见 OOM 原因及解决方案
本文可以结合《 Sun JVM 内存管理、GC 工作流程、JVM 参数与调优》、《JVM 规范与 Sun JVM 实现、运行时数据区域、垃圾分代回收算法》查看。
Java 栈(Stack)
1、Java 栈是与每一个线程关联的,JVM 在创建每一个线程的时候,会分配一定的栈空间给线程,Java Stack 为每个线程独享。
2、Java Stack 主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文(对象的引用), 以帧为单位保存线程的运行状态。
3、栈空间随着线程的终止而释放。
4、StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么 JVM 就会抛出此异常,这种情况一般是死递归造成的。
Java 堆(Heap)
1、Java 中堆是由所有的线程共享的一块内存区域,堆用来保存各种 JAVA 对象,比如数组,线程对象等。
2、JVM 堆一般又可以分为以下三部分:
这里也可以参考《 Sun JVM 内存管理、GC 工作流程、JVM 参数与调优》
Perm(永久区) | 1、Perm 代主要保存 class(类,包括接口等),method(方法),filed(属性) 等元数据,这部分的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到热部署的应用服务器的时候,有时候会遇到 java.lang.OutOfMemoryError : PermGen space 的错误,造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的 class 没有被卸载掉,这样就造成了大量的 class 对象保存在了 perm 中,这种情况下,一般重新启动应用服务器可以解决问题。 |
Tenured(年老代) | 1、Tenured 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在 Young 复制转移一定的次数以后,对象就会被转移到 Tenured 区,一般如果系统中用了 application 级别的缓存,缓存中的对象往往会被转移到这一区间。 |
Young(年轻代) |
1、Young 区被划分为三部分,Eden(伊甸园) 区和两个大小严格相同的 Survivor(幸存者)区,其中 Survivor 区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用。 2、在 Young 区间变满的时候,minor GC 就会将存活的对象移到空闲的 Survivor 区间中,根据 JVM 的策略,在经过几次垃圾收集后,任然存活于 Survivor 的对象将被移动到 Tenured 区间。 |
堆 (Heap) VS 栈 (Stack)
1、Java 中用堆来存储对象,一旦堆中的对象被销毁,继续引用这个对象的话,就会出现著名的 NullPointerException。
2、栈没有堆灵活,但是更严格,是安全的,易于管理,因为只要上面的引用没有销毁,下面引用就一定还在,所以,在栈中,上面引用永远可以通过下面引用来查找对象,同时如果确认某一区间的内容会一起存在、一起销毁,也可以上下互相引用。
3、在大部分程序中,都是先定义的变量、引用先进栈,后定义的后进栈,同时,区块内部的变量、引用在进入区块时压栈,区块结束时出栈,理解了这种机制,就可以很方便地理解各种编程语言的作用域的概念了。
栈:存放变量引用的地方,以及基本数据类型 堆:存放实际对象的地方,即数组、线程对象等。 |
举例说明
int i = 7; 存在栈里边的,内容为 i = 7。
String s = "Hello World!"; 这个是存在另外一块静态代码区。
Apple app = new Apple(); app 引用存在栈里,引用地址对应对象 Apple 在堆里。
常见 OOM 原因及解决方案
1、当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误
一)Java heap space
1、当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出 java.lang.OutOfMemoryError:Javaheap space
错误.
2、Javaheap space
错误产生的常见原因可以分为以下几类:
1、请求创建一个超大对象,通常是一个大数组。 2、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。 3、过度使用终结器(Finalizer),该对象没有立即被 GC。 4、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收。 |
3、针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可,如果仍然没有解决,可以参考以下情况做进一步处理:
1、如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。 2、如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。 3、如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。 |
2)GC overhead limit exceeded
1、当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded
错误。
2、简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收,此类问题的原因与解决方案跟 Javaheap space
类似。
三)Permgen space
1、该错误表示永久代(Permanent Generation)已用满,通常是因为加载的 class 数目太多或体积太大。
2、永久代存储对象主要包括以下几类:
1、加载/缓存到内存中的 class 定义,包括类的名称,字段,方法和字节码; 2、常量池; 3、对象数组/类型数组所关联的 class; 4、JIT 编译器优化后的 class 信息。 |
3、PermGen 的使用量与加载到内存的 class 的数量/大小正相关。
4、根据 Permgen space 报错的时机,可以采用不同的解决方案,如下所示:
1、程序启动报错,修改 -XX:MaxPermSize 启动参数,调大永久代空间。 2、应用重新部署时报错,很可能是应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决。 3、运行时报错,应用程序可能会动态创建大量 class,而这些 class 的生命周期很短暂,但是 JVM 默认不会卸载 class,可以设置 |
四)Metaspace
1、JDK 1.8 使用 Metaspace 替换了永久代(Permanent Generation),该错误表示 Metaspace 已被用满,通常是因为加载的 class 数目太多或体积太大。
2、此类问题的原因与解决方法跟 Permgenspace
非常类似,可以参考上文。需要特别注意的是调整 Metaspace 空间大小的启动参数为 -XX:MaxMetaspaceSize
。
JVM 堆、栈概述 与 常见 OOM 原因及解决方案相关推荐
- 悬浮细胞、淋巴细胞培养常见失败原因及解决方案
一.严格无菌操作 对实验室以及培养过程中所接触的试剂.液体.器皿.仪器的消毒,均应严格按照有关细胞培养的参考书的要求进行操作.无菌观念要贯穿整个实验的始终,不可松懈. 二.培养器皿的选择 淋巴细胞培养 ...
- JVM堆 栈 方法区详解
一.栈 每当启用一个线程时,JVM就为他分配一个JAVA栈,栈是以帧为单位保存当前线程的运行状态 栈是由栈帧组成,每当线程调用一个java方法时,JVM就会在该线程对应的栈中压入一个帧 只有在调用一个 ...
- ChatGPT 常见错误原因及解决方案:报错、回答不完整、网络错误等
最近,由人工智能实验室 OpenAI 发布的对话式大型语言模型 ChatGPT 火得一塌糊涂.它可以与人类轻松地对话,无论是多么奇葩的问题 ChatGPT 都不在话下.在体验 ChatGPT 的同时我 ...
- 常见的 OOM 原因及其解决方法(OutOfMemoryError)
当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误.本文总结了常见的 OOM 原因及其解决方法,如下图所示.如有遗漏或错误,欢迎补充指正. 1.Java ...
- javaheapspace解决方案_高手总结的9种 OOM 常见原因及解决方案
当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误.本文总结了常见的 OOM 原因及其解决方法,如下图所示.如有遗漏或错误,欢迎补充指正. 1.Java ...
- 九种 OOM 常见原因及解决方案(IT枫斗者)
九种 OOM 常见原因及解决方案(IT枫斗者) 什么是OOM? OOM,全称"Out Of Memory",翻译成中文就是"内存用完了",来源于java.lan ...
- Java JVM堆空间的概述
Java JVM堆空间的概述 1.设置堆空间初始值和最大值 2.堆的核心概述 内存细分 3.堆空间大小的设置 4.新生代与老年代 5.图解对象分配的过程 6.常用调优工具 7.Minor GC.Maj ...
- 高手总结的9种 OOM 常见原因及解决方案
高手总结的9种 OOM 常见原因及解决方案 [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行 ...
- JVM内存参数设置及常见错误总结
一. JVM规范 JVM规范对Java运行时的内存划定了几块区域(详见这里),有:JVM栈(Java Virtual Machine Stacks).堆(Heap).方法区(Method Area) ...
- Java程序员必备:常见OOM异常分析
前言 放假这几天,温习了深入理解Java虚拟机的第二章, 整理了JVM发生OOM异常的几种情况,并分析原因以及解决方案,希望对大家有帮助. Java 堆溢出 Java堆用于存储对象实例,只要不断 ...
最新文章
- CREATE TABLESPACE
- 【 MATLAB 】Fourier Transforms ( fft )
- FIFOQueue '_4_batch_processing/batch_join/fifo_queue' is closed and has insu
- python中保留小数_python保留小数位的三种实现方法
- failed to get the task for process XXX(解决方案)
- Oracle中如何删除某个用户下的所有数据的方法
- Ubantu18.04安装Vivado
- 3DMax插件和它的3DXI接口
- C语言 将整数写入内存指定的连续字节单元中
- 数据科学与大数据技术的案例_主数据科学案例研究,招聘经理的观点
- HTTPS加密传输过程
- 虹软人脸识别在 linux中so文件加载不到的问题
- “谷歌杀手”发明者,科学天才 Wolfram
- C++ typename 的双重含义
- IOS UIwebView 加载网络图片 使用相对地址
- 用Wineskin在Mac上运行exe文件
- 观天涯kk大神10年帖子有感
- Python爬取手机号码前7位号段归属地及运营商
- Linux基础知识介绍
- Oracle中rowid的用法(全面)
热门文章
- 接口和抽象类的区别(转载)
- (Oracle、SqlServer、Access)数据库开发代码生成工具SharpCode2.0
- cout和printf的区别
- mysql left join_对比MySQL,教你在Pandas中实现SQL常用操作!
- 拓端tecdat|R语言Black Scholes和Cox-Ross-Rubinstein期权定价模型案例
- 拓端tecdat|R语言中使用多重聚合预测算法(MAPA)进行时间序列分析
- 拓端tecdat|Stata估算观测数据的风险比
- 拓端tecdat|R语言中实现层次聚类模型
- 【大数据部落】R语言实现:混合正态分布EM最大期望估计法
- R语言周氏检验(Chow test) 检验回归中结构不稳定性的虚拟变量的替代方案