- 浏览: 1064303 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
flyfeifei66:
list<bean> bean 中有 list&l ...
freemarker中的list -
BelloVersion:
第五种错误Remote host closed connect ...
客户端如何使用httpclient向https服务器发送数据 -
willxue:
看了半天 前面说的是错的?。。。
反向键索引的原理和用途 -
liulanghan110:
quainter 写道麻烦博主,参数为数组时,paramete ...
MYBATIS 的parameter -
quainter:
麻烦博主,参数为数组时,parameterType怎么写啊?
MYBATIS 的parameter
1.JAVA堆导致的内存异常
Java堆存放的是对象实例,因此只要不断建立对象,并且保证GC Roots到对象之间有可达路径即可产生OOM异常。这是由于内存泄露导致的内存溢出异常。代码如下:
package MemoryTest; import java.util.ArrayList; import java.util.List; /** * Java堆OOM测试 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * @author zzm */ public class HeapOOM { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<OOMObject>(); while (true) { list.add(new OOMObject()); } } }
测试中限制Java堆大小为20M,不可扩展,通过参数-XX:+HeapDumpOnOutOfMemoryError让虚拟机在出现OOM异常的时候Dump出内存映像以便分析。
注:虚拟机参数设置。窗口->首选项->JAVA->已安装的JRE,在缺省的VM自变量中增加。
运行结果:
stack length:11347 Exception in thread "main" java.lang.StackOverflowError at MemoryTest.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:16)
关于VM栈和本地方法栈在VM Spec描述了两种异常:StackOverflowError与OutOfMemoryError,当栈空间无法继续分配分配时,到底是内存太小还是栈太大其实某种意义上是对同一件事情的两种描述而已.
1.使用-Xss参数削减栈内存容量。结果:抛出SOF异常时的堆栈深度相应缩小。 2.定义大量的本地变量,增大此方法对应帧的长度。结果:抛出SOF异常时的堆栈深度相应缩小。 3.创建几个定义很多本地变量的复杂对象,打开逃逸分析和标量替换选项,使得JIT编译器允许对象拆分后在栈中分配。结果:实际效果同第二点。
stack length:2402 Exception in thread "main" java.lang.StackOverflowError at MemoryTest.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14) at MemoryTest.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:16)
如果在多线程环境下,不断建立线程倒是可以产生OOM异常,但是基本上这个异常和VM栈空间够不够关系没有直接关系,甚至是给每个线程的VM栈分配的内存越多反而越容易产生这个OOM异常。
原因其实很好理解,操作系统分配给每个进程的内存是有限制的,譬如32位Windows限制为2G,Java堆和方法区的大小JVM有参数可以限制最大值,那剩余的内存为2G(操作系统限制)-Xmx(最大堆)-MaxPermSize(最大方法区),程序计数器消耗内存很小,可以忽略掉,那虚拟机进程本身耗费的内存不计算的话,剩下的内存就供每一个线程的VM栈和本地方法栈瓜分了,那自然每个线程中VM栈分配内存越多,就越容易把剩下的内存耗尽。
创建线程导致OOM异常
设置好虚拟机参数后,运行上面的代码。特别提示运行上面这段代码,记得要存盘当前工作,上述代码执行时有很大令操作系统卡死的风险。结果:
运行时常量池
package MemoryTest;
/*
* 创建线程导致OOM异常
* VM Args:-Xss2M (这时候不妨设大些)
* @author zzm
*/
public class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable {
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
要在常量池里添加内容,最简单的就是使用String.intern()这个Native方法。由于常量池分配在方法区内,我们只需要通过-XX:PermSize和-XX:MaxPermSize限制方法区大小即可限制常量池容量。实现代码如下:
package MemoryTest; import java.util.ArrayList; import java.util.List; /* * 运行时常量池导致的OOM异常 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M * @author zzm */ public class RuntimeConstantPoolOOM { public static void main(String[] args) { // 使用List保持着常量池引用,压制Full GC回收常量池行为 List<String> list = new ArrayList<String>(); // 10M的PermSize在integer范围内足够产生OOM了 int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } }
设置好虚拟机参数后运行,结果如下:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at MemoryTest.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:29)
方法区
方法区用于存放Class相关信息,所以这个区域的测试我们借助CGLib直接操作字节码动态生成大量的Class,值得注意的是,这里我们这个例子中模拟的场景其实经常会在实际应用中出现:当前很多主流框架,如Spring、Hibernate对类进行增强时,都会使用到CGLib这类字节码技术,当增强的类越多,就需要越大的方法区用于保证动态生成的Class可以加载入内存。
package MemoryTest; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodInterceptor; /* 需要下载cglib * 借助CGLib使得方法区出现OOM异常 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M * @author zzm */ public class JavaMethodAreaOOM { public static void main(String[] args) { while (true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor(){ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, args); } }); enhancer.create(); } } static class OOMObject { } }
结果:
Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method)
本机直接内存
设置好参数后运行,结果 package MemoryTest;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/*
* 本机直接内存
* VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
* @author zzm
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method) at MemoryTest.DirectMemoryOOM.main(DirectMemoryOOM.java:35)
2.VM栈和本地方法栈
设置虚拟机参数后运行程序,结果如下:
发表评论
-
JAVA内存分析
2017-09-30 18:42 439jmap -heap pid : 查看堆的使用状况信息 ... -
java dump线程日志
2016-02-15 10:52 1468JVM 自带的工具获取线程堆栈: JDK自带命令行工具获取 ... -
spring 拦截器
2015-05-05 16:07 8321.拦截器配置 <mvc:intercepto ... -
用 ThreadLocal 管理用户session
2014-11-10 15:47 9190很多项目中需要在代码中使用当前登录用户的信息,但是又不方便把 ... -
JAVA并发控制的几种办法
2014-08-25 16:43 2742假如有十张票,现在 ... -
synchronized
2014-08-21 16:58 1247synchronized 关键字的作 ... -
非阻塞同步机制与CAS操作
2014-07-29 16:07 1390锁的劣势 Java ... -
线程简介(转)
2014-04-21 12:06 767一、线程概述 线程是 ... -
什么是线程,如何创建线程
2014-04-21 12:03 919如果你学习过操作系统 ... -
线程池有助于实现最佳资源利用率
2014-04-21 10:01 1420为什么要用线程池? 诸如 Web 服务器、数据库服务器、 ... -
spring实现初始化和销毁bean之前进行的操作
2014-03-03 19:01 971第一种:通过@PostConstruct 和 @PreDes ... -
文章自动添加超链接
2014-01-14 16:01 2176在网上可以发现,很多文章中的关键词会有超链接,超链接的实现 ... -
JVM 内存监控
2013-11-28 14:17 1038jps Java进程查看工具,实际上它和Unix/Lin ... -
freemarker操作字符串,数字,布尔类型函数
2013-11-26 16:45 6605布尔类型 1. 后台不能将值设置为Boolean对 ... -
汉字转拼音
2013-11-26 16:39 1192import net.sourceforge.pinyin4 ... -
birt读取现有系统的数据库配置作为数据源
2013-09-10 13:51 3799Birt的数据源可以用多种形式,当我们把BIRT嵌入到现有 ... -
birt动态SQL
2013-07-26 18:05 9056birt动态SQL实现有三种方式:拼接SQL、绑定变量和让 ... -
关于spring事务
2013-06-13 14:44 983在ORACLE数据库中,一般DDL语句是隐式COMMIT提交 ... -
Tomcat Server是如何处理http请求的
2013-05-08 10:24 1292假设来自客户的请求为:http://localhost:8 ... -
注解annotation
2013-05-07 14:40 1093ava注解是附加在代码中的一些元信息,用于一些工具在编译、运 ...
相关推荐
1 2.1有关线程你必须知道的事 3 2.3volatile与Java内存模型(JMM) 2 2.2初始线程:线程的基本操作 4 2.4分门别类的管理:线程组 2java并行程序基础 5 2.5驻守后台:守护线程(Daemon) 6 2.6先做重要的事:线程...
书名:《Java开发实战1200例(第I卷)》(清华大学出版社.李钟尉,陈丹丹) PDF格式扫描版,全书分为24章,共817页。2011年1月出版。 全书压缩打包成4部分,这是第3部分 注:本系列图书的第I、II卷再版时均相应改名为...
第2章 Java内存区域与内存溢出异常 / 24 2.1 概述 / 24 2.2 运行时数据区域 / 25 2.2.1 程序计数器 / 25 2.2.2 Java虚拟机栈 / 26 2.2.3 本地方法栈 / 27 2.2.4 Java堆 / 27 2.2.5 方法区 / 28 2.2.6 运行...
原子性、可见性和有序性在Java内存模型中的体现;先行发生原则的规则和使用;线程在Java语言中的实现原理;虚拟机实现高效并发所做的一系列锁优化措施。 前言 第一部分 走近Java 第1章 走近Java 1.1 概述 1.2 ...
第三节:Java内存模型 ························································ 35 第四节:内存屏障与JVM指令 ··················...
技术点41 内存交换技术点42 磁盘健康技术点43 网络6.3 可视化技术点44 提取并可视化任务执行时间6.4 优化 .6.4.1 剖析MapReduce 的用户代码 技术点45 剖析map 和reduce 任务 6.4.2 参数配置6.4.3...
├─3.03 Nginx进阶-配置提升-Nginx错误页面.mp4 ├─3.04 Nginx进阶-配置提升-访问控制.mp4 ├─3.05 Nginx进阶-配置提升-流量控制.mp4 ├─3.06 Nginx进阶-提升配置-流量控制.mp4 ├─3.07 Nginx进阶-配置提升-...
2.7基础语法实战演习88 2.7.1判断闰年88 2.7.2求最大公约数和最小公倍数89 2.7.3Fibonacci数列90 2.7.4逆向输出数字91 2.7.5求水仙花数92 2.7.6输出图形93 2.7.7输出九九口诀表94 2.8本章小结95 第2篇Java...
写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘...
其实还有更简单的方法,而且是更好的方法,使用合理描述参数和SQL语句返回值的接口(比如IUserOperation.class),这样现在就可以至此那个更简单,更安全的代码,没有容易发生的字符串文字和转换的错误.下面是详细...
6.4.5 在MapReduce 中优化用户的Java 代码 6.4.6 数据序列化 6.5 本章小结 第4 部分 数据科学. 7 数据结构和算法的运用 7.1 使用图进行数据建模和解决问题 7.1.1 模拟图 7.1.2 最短路径算法 技术...
17.3.1 我想修正犯下的错误 316 17.3.2 第二天的解决方案 317 17.4 第三天:评判日 320 17.5 也来玩下这个游戏吧 327 第18章 可扩展Visitor模式的案例 328 18.1 抽象类 331 18.2 为改进做好准备...
•在java类里只能包含Field,方法,构造器,初始化块,内部类(接口、枚举)等5种成员。 用static修饰的类成员属 于类成员,类Field既可通过类来访问,也可以通过类的对象来访问。当通过对象来访问类属性时,系统会在底...
这是因为某个servlet(服务器端Java程序)在应用户的请求而首次调入内存执行之后将一直驻留在内存里,对同一个servlet的后续请求不用再对这个servlet的类进行实例化,因此响应速度更快。 可是,servlet也存在一个...