JVM异常之:堆溢出OutofMemoryError
1、堆溢出
Java 堆内存的OutOfMemoryError异常是实际应用中最常见的内存溢出异常情况。出现Java 堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。
要解决这个区域的异常,一般的手段是首先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump 出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。使用Eclipse Memory Analyzer 打开的堆转储快照文件。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots 引用链的信息,就可以比较准确地定位出泄漏代码的位置。
如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。
以上是处理Java 堆内存问题的简略思路,处理这些问题所需要的知识、工具与经验在后面的几次分享中我会做一些额外的分析。
示例:
package com.dxz.jvm; import java.util.ArrayList;
import java.util.List; /**
* @Described:堆溢出测试
* @VM args:-verbose:gc -Xms20M -Xmx20M -XX:+PrintGCDetails
*/
public class HeapOutOfMemory { public static void main(String[] args) {
List<TestObject> cases = new ArrayList<TestObject>();
HeapOutOfMemory heapOutOfMemory = new HeapOutOfMemory();
while (true) {
cases.add(heapOutOfMemory.new TestObject()); }
} public class TestObject {
private double a = 34.53;
private Integer b = 9999999;
}
}
结果:
2、常量池溢出(常量池都有哪些信息,我们在后续的JVM类文件结构中详细描述)
2.1、方法区溢出(Perm持久代溢出)
在jdk1.6及之前的版本中,常量池放在Perm区也即是方法区中,所以在jdk1.6版本中,常量池溢出可以说是方法区溢出。
方法区溢出的示例见《JVM体系结构之七:持久代、元空间(Metaspace) Metaspace 之三--了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap》
在网络上看到一个cglib导致的方法区溢出的示例:
package com.dxz.jvm; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; /**
* @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public class MethodAreaOutOfMemory { public static void main(String[] args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MethodAreaOutOfMemory.TestObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
return arg3.invokeSuper(arg0, arg2);
}
});
enhancer.create();
}
} public static class TestObject {
private double a = 34.53;
private Integer b = 9999999;
}
}
运行结果:
- Caused by: java.lang.OutOfMemoryError: PermGen space
- at java.lang.ClassLoader.defineClass1(Native Method)
- at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
- at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
- ... 8 more
方法区溢出也是一种常见的内存溢出异常,一个类要被垃圾收集器回收掉,判定条件是比较苛刻的。在经常动态生成大量Class的应用中,需要特别注意类的回收状况。这类场景除了上面提到的程序使用了CGLib字节码增强和动态语言之外,常见的还有:大量JSP或动态产生JSP文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGi的应用(即使是同一个类文件,被不同的加载器加载也会视为不同的类)等。
2.2、常量池导致的堆溢出
在jdk1.7以后,perm持久代已经被移除,常量池也放到了堆中,其导致的溢出也变成了堆溢出。
示例见《JVM体系结构之七:持久代、元空间(Metaspace) Metaspace 之三--了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap》
JVM异常之:堆溢出OutofMemoryError的更多相关文章
- java代码实现JVM栈溢出,堆溢出
参考博客:http://www.cnblogs.com/tv151579/p/3647238.html 背景知识: 栈存放什么:栈存储运行时声明的变量——对象引用(或基础类型, primitive)内 ...
- OutOfMemoryError异常——Java堆溢出。
https://blog.csdn.net/en_joker/article/details/79726975 (将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数- ...
- Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)
转载自https://github.com/pzxwhc/MineKnowContainer/issues/25 包括:1. 栈溢出(StackOverflowError)2. 堆溢出(OutOfMe ...
- JVM 内存溢出详解(栈溢出,堆溢出,持久代溢出、无法创建本地线程)
出处: http://www.jianshu.com/p/cd705f88cf2a 1.内存溢出和内存泄漏的区别 内存溢出 (Out Of Memory):是指程序在申请内存时,没有足够的内存空间供 ...
- JVM探秘2--详解内存溢出OutOfMemoryError异常
JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...
- JVM异常之:方法区溢出OutOfMemoryError: PermGen space
1.方法区溢出(Perm持久代溢出) 在jdk1.6及之前的版本中,常量池放在Perm区也即是方法区中,所以在jdk1.6版本中,常量池溢出可以说是方法区溢出. 示例一: 方法区溢出的示例见<J ...
- JVM的参数设置与OutOfMemoryError异常关系
Java堆中存放Object对象数据,例如new出来的Object.当没有任何引用指向某对象时,该对象可能被垃圾回收.有关垃圾回收算法,可参考其他有关文章,网上很多.关于对象引用,按强弱还有强引用,软 ...
- JVM--你常见的jvm 异常有哪些? 代码演示:StackOverflowError , utOfMemoryError: Java heap space , OutOfMemoryError: GC overhead limit exceeded, Direct buffer memory, Unable_to_create_new_native_Thread, Metaspace
直接上代码: public class Test001 { public static void main(String[] args) { //java.lang.StackOverflowErro ...
- JVM(2) Java内存溢出异常
在Java虚拟机运行时数据区中,除了程序计数器之外,虚拟机栈.本地方法栈.方法区和Java堆都有发生OutOfMemoryError(简称OOM)异常的可能. 一.Java堆溢出 Java堆用于存储对 ...
随机推荐
- Cocos闪屏视频VideoPlayer踩坑记录
游戏闪屏动画(Logo&健康游戏公告)使用了 experimental::ui::VideoPlayer 来播放视频 3.7版本开发到目前为止发现2个坑 1.设置大小 _videoPlayer ...
- LeetCode - Reorganize String
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
- LA5009 Error Curves
题意 PDF 分析 因为这些函数都可以看成下凸的,所以总函数也是下凸的(可用反证法证明). 三分答案即可,时间复杂度\(O(100)\) 代码 #include<bits/stdc++.h> ...
- Object 及toString() 方法的重写
Object: 是所有的类的父类 ,Object中所有的方法 , 子类都能使用 , 接口不是Object子类. Person: /*将父类的equals方法 重写 * 不改变父类的源代码 eq ...
- Using Elixir Dynamic Supervisors
转自: https://blog.smartlogic.io/elixir-dynamic-supervisors/ I have been working on my side project Gr ...
- apache常用配置文件讲解
apache 的httpd.conf常用配置说明 # ServerRoot: The top of the directory tree under which the server's # conf ...
- Monte Carlo tree search 学习
https://en.wikipedia.org/wiki/Monte_Carlo_tree_search 蒙特卡洛树搜索(MCTS)基础 http://mcts.ai/about/index.htm ...
- OSGI基础知识整理
一. 简介: OSGi(Open Service Gateway Initiative)技术是面向Java的动态模型系统. OSGi的主要职责就是为了让开发者能够创建动态化.模 ...
- sql server 附加只有mdf的数据库文件
有时候SQL Server意外断电会导致SQL Server的ldf日志文件丢失或者损坏,这个时候你如果直接附加mdf文件到SQL Server会失败,这里提供一个方法可以还原只有mdf的数据库文件, ...
- 打造mac上最好用的Terminal
出处:https://blog.csdn.net/kebing1011/article/details/46934533?utm_source=blogxgwz0