- 浏览: 1076705 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
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 509jmap -heap pid : 查看堆的使用状况信息 ... -
java dump线程日志
2016-02-15 10:52 1555JVM 自带的工具获取线程堆栈: JDK自带命令行工具获取 ... -
spring 拦截器
2015-05-05 16:07 8771.拦截器配置 <mvc:intercepto ... -
用 ThreadLocal 管理用户session
2014-11-10 15:47 9253很多项目中需要在代码中使用当前登录用户的信息,但是又不方便把 ... -
JAVA并发控制的几种办法
2014-08-25 16:43 2780假如有十张票,现在 ... -
synchronized
2014-08-21 16:58 1298synchronized 关键字的作 ... -
非阻塞同步机制与CAS操作
2014-07-29 16:07 1435锁的劣势 Java ... -
线程简介(转)
2014-04-21 12:06 807一、线程概述 线程是 ... -
什么是线程,如何创建线程
2014-04-21 12:03 972如果你学习过操作系统 ... -
线程池有助于实现最佳资源利用率
2014-04-21 10:01 1476为什么要用线程池? 诸如 Web 服务器、数据库服务器、 ... -
spring实现初始化和销毁bean之前进行的操作
2014-03-03 19:01 1016第一种:通过@PostConstruct 和 @PreDes ... -
文章自动添加超链接
2014-01-14 16:01 2209在网上可以发现,很多文章中的关键词会有超链接,超链接的实现 ... -
JVM 内存监控
2013-11-28 14:17 1083jps Java进程查看工具,实际上它和Unix/Lin ... -
freemarker操作字符串,数字,布尔类型函数
2013-11-26 16:45 6691布尔类型 1. 后台不能将值设置为Boolean对 ... -
汉字转拼音
2013-11-26 16:39 1242import net.sourceforge.pinyin4 ... -
birt读取现有系统的数据库配置作为数据源
2013-09-10 13:51 3865Birt的数据源可以用多种形式,当我们把BIRT嵌入到现有 ... -
birt动态SQL
2013-07-26 18:05 9119birt动态SQL实现有三种方式:拼接SQL、绑定变量和让 ... -
关于spring事务
2013-06-13 14:44 1021在ORACLE数据库中,一般DDL语句是隐式COMMIT提交 ... -
Tomcat Server是如何处理http请求的
2013-05-08 10:24 1336假设来自客户的请求为:http://localhost:8 ... -
注解annotation
2013-05-07 14:40 1128ava注解是附加在代码中的一些元信息,用于一些工具在编译、运 ...
相关推荐
垃圾收集机制是Java内存管理的一大特色,它自动回收不再使用的对象所占用的内存,避免了程序员手动管理内存的繁琐。了解垃圾收集的工作原理和各种垃圾收集器,如Serial、Parallel、CMS和G1,对于优化程序性能至关...
了解JVM的基本工作原理对于Java开发者来说是基础,包括其内存模型、垃圾收集机制、执行引擎等。 2. 标准输入输出:文档中提到使用键盘输入来完成程序的输入部分,这涉及到Java中标准输入输出流(System.in, System....
### Java内存泄露、溢出检查方法及工具详解 #### 一、引言 在实际的项目开发和运维过程中,经常会遇到Java应用程序出现内存溢出(`java.lang.OutOfMemoryError`)的情况。这类问题不仅影响应用程序的稳定性和性能...
#### 五、Java内存模型与管理 Java虚拟机(JVM)对内存的管理分为几个主要部分: - **堆**(Heap):用于存储所有Java对象实例的内存区域。堆的大小可以通过`-Xmx`和`-Xms`命令行选项进行调整。 - **方法区**(Method ...
4. **Java虚拟机(JVM)原理**:了解JVM的工作机制,包括内存管理、垃圾回收、类加载过程等,优化应用程序的性能。 5. **单元测试与持续集成**:掌握JUnit等测试框架的使用,实施自动化测试和持续集成,确保代码质量...
《JAVA内存调优白皮书(IBM)》是IBM公司发布的一份技术文档,主要针对Java应用程序的内存管理和性能优化提供了深入的指导。在Java世界中,内存管理是决定程序性能、稳定性和可扩展性的重要因素,特别是Java虚拟机...
10. **JVM内存管理**:Java的垃圾收集器是自动内存管理的关键,PPT会讲解堆内存、栈内存以及垃圾回收机制。 11. **设计模式**:作为软件开发的良好实践,设计模式如单例、工厂、观察者等会在PPT中得到详细解读,...
此外,书中还详细讲解了Java内存模型(JMM),这是理解多线程间数据同步和可见性的重要理论基础。 接着,书中深入探讨了Java并发库的使用,如java.util.concurrent包下的ExecutorService、Future、Callable接口,...
3. **异常处理**:Java通过异常处理机制来处理运行时错误,通过try-catch-finally语句块捕获和处理异常,以确保程序的健壮性。书中会详细讲解如何正确使用异常处理来编写稳定代码。 4. **IO与NIO**:Java的输入/...
10. **最佳实践**:项目实战提供了应用最佳编程和大数据处理实践的机会,例如模块化设计、代码复用、错误处理等。 总之,这个压缩包中的项目实战涵盖了Java编程和大数据处理的多个方面,是理论学习与实际操作相结合...
10. **异常处理**:Java异常处理是程序错误处理的重要手段。通过理解异常的层次结构、如何抛出和捕获异常,可以编写健壮的程序。 以上知识点都是《JAVA开发实战经典》一书可能涉及的内容,通过源代码的学习和实践,...
在实战项目中,你将有机会深入理解这些框架的工作原理,学习如何利用Java API进行数据读写、数据转换、作业提交和错误处理等。每个框架都有其特定的应用场景和优缺点,比如Hadoop适合离线批处理,Spark适用于交互式...
其次,书中深入剖析了Java内存模型(JMM)和可见性问题,这是理解并发编程中数据一致性问题的基础。Java的volatile关键字、synchronized块和方法、以及Atomic类都是解决这些问题的关键工具。作者通过实际案例解释了...
《Java并发编程实战》这本书是Java开发者深入理解并发编程的重要参考资料。书中的内容涵盖了Java并发编程的各个方面,包括基础概念、线程管理、同步机制、并发工具类以及高性能并发设计模式等。以下是对这些知识点的...
### Java内存分配详解 #### 一、Java内存区域与内存溢出异常 Java虚拟机(JVM)在运行过程中会管理多种不同的内存区域,这些区域各自承担着特定的任务,并且每种区域都有可能发生内存溢出异常。 ##### 1.1 程序...
本实战课程聚焦于提升Java程序的性能,涵盖了多个关键领域,包括Java编程、JVM性能监测与调优、多线程性能优化以及数据库性能优化等。 首先,模块一概述部分可能介绍了性能调优的基本概念和重要性,以及Java性能...
### Java软件开发实战知识点梳理 #### 1-1 什么是Java - **计算机编程语言**:Java是一种面向对象的编程语言。 - **软件开发平台**:提供了完整的开发环境,包括编译器、解释器和一系列工具。 - **软件运行平台**:...
Java高级程序设计实战教程是深入理解并提升Java编程技能的重要资源。这个压缩包"Java高级程序设计实战教程-源代码.rar"很可能包含了丰富的实例代码,旨在帮助学习者通过实践来掌握高级Java编程概念。标签“教学资料...
理解内存模型、垃圾回收机制以及如何分析和优化性能,是提升Java应用效率的关键。笔记中可能包含JVM参数调整实例和性能监控工具的使用方法。 最后,Spring框架的使用是企业级Java开发的常见实践。Spring的依赖注入...
### Java软件开发实战:Java基础与案例开发详解 #### 1-2 认识Java语言 **1.2.1 Java语言的特性** Java是一种功能强大且用途广泛的编程语言,其核心特性包括: 1. **简单高效**:Java语言的设计理念之一就是简单...