今天花了一整天在跟踪一个问题,每次感觉已经快找到原因的时候发现现象又变了,我觉得从中吸取的教训可以给大家分享一下。
为了重现这个现象,我写了一个简单的例子。在本例中,先初始化了一个map,然后用一个无限循环将一些键值对插入到map里面:
class Wrapper {
public static void main(String args[]) throws Exception {
Map map = System.getProperties();
Random r = new Random();
while (true) {
map.put(r.nextInt(), "value");
}
}
}
你可能也猜到了,这段代码编译执行后无法正常结束。当我用这组参数启动的话:
java -Xmx100m -XX:+UseParallelGC Wrapper
我会在终端中看到java.lang.OutOfMemoryError: GC overhead limit exceeded的异常信息。不过如果我调整一下堆大小或者是GC的类型的话,在我的Mac OS X 10.9.2 系统上用Oracle Hotspot JDK 1.7.0_45来运行,就会出现不同的情况。
比如说,我用一个较小的堆来运行这个程序,就像下面这样:
java -Xmx10m -XX:+UseParallelGC Wrapper
应用程序会抛出一段大家更熟悉的错误信息然后挂掉:java.lang.OutOfMemoryError: Java heap space。
如果你换成ParallelGC以外的GC策略的话,比如说-XX:+UseConcMarkSweepGC or -XX:+UseG1GC,你将会看到由默认的异常处理器所抛出的异常,并且你看不到堆栈信息了,因为堆已经没有空间了,甚至连异常的堆栈信息都没法填充了,因此它在创建异常的时候就挂掉了:
My Precious:examples vladimir$ java -Xmx100m -XX:+UseConcMarkSweepGC Wrapper
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
这说明了什么?当资源紧缺的时候,你根本没法判断你的应用程序是怎么挂掉的,因此不要指望能出现你所预期的一系列错误提示。从上面这个例子中可以看到,你的程序可能会以三种完全不同的方式挂掉:
1. GC的安全性检查失败:一旦GC花费的时间占到98%以上的话,JVM就会宣告投降了: java.lang.OutOfMemoryError: GC overhead limit exceeded。
2. 无法为下一个操作分配足够的内存:如果无法满足下一条指令所需要分配的内存的话,你会收到一条”java.lang.OutOfMemoryError: Java heap space” 的错误信息。
3. 你可能也总结出来了,还有一种情况是你的内存已经紧张到连JVM创建一条OutOfMemoryError异常,填充堆栈信息,打印到屏幕上这点要求都满足不了了。这种情况UncaughtExceptionHandler会捕获到这个错误,而不再走通常的错误流程。这个处理器恰如其名,当线程由于某个异常快要挂掉的时候,它开始出来收场了。出现这种情况的话,JVM会找到线程对应的 UncaughtExceptionHandler,然后调用它的uncaughtException方法。
因此当你捕获到内存不足的异常并自以为已经胸有成竹时,请再多思考一下 。系统已经处于崩溃的边缘,你原认为你能依赖的信息很可能会消失或者改变。留给你的只有一脸茫然,正如我前面那12个小时中那样。
如果你已经耐心读到这了,我推荐你关注下我们的
twitter帐号。我们每周都会发一些工作中碰到的一些性能调优的问题。
原创文章转载请注明出处:
http://it.deepinmind.com
英文原文链接
分享到:
相关推荐
Java程序设计一种跨学科的方法 代码,作者:(美国)赛德维克 (美国)韦恩 译者:葛秀慧 田浩
实用性:《Java程序设计习题集》每章都含有一些趣味题,营造了一种轻松而快乐的学习氛围,努力培养和提高学生的学习乐趣,同时也使学生容易产生学习成就感。 趣味性:习题基本上覆盖了程序员在编写Java程序时...
自己写的一小段Java程序,让程序按条件自动重新启动,3个文件都是.java文件,程序不包含包信息,可以放到C盘直接进行编译运行,其中Test是运行主程序,watch是监视检测线程
Java程序设计与项目实践配套光盘
雍俊海 Java程序设计教程 第二版答案(代码部分)
这个bat脚本资源可以在Windows环境下实现Java程序的守护进程和自动重启。它通过一个循环监控Java程序进程,如果检测到程序异常退出,会自动重启程序。同时具有可配置的重启次数和重启间隔时间。 这个小巧但实用的bat...
Java是一种编程语言,它具有简单、高效、健壮、安全、与平台无关、可移植性好和多线程等特点,是一种纯面向对象的、网络编程首选的语言。Java是一个平台,它支持从智能卡应用、手持式电子消费类产品应用、桌面应用到...
张洪斌的java程序设计百事通
研究生java 课件 配套Java程序设计实用教程 附带源代码
Java Web程序设计教程 Java Web程序设计教程
不错的Java小程序,适合初学者学习和交流
java中两种方式调用其他.exe可执行程序
Java程序设计教程(第四版)中文 part6 The end~~~
目录第1章 Java语言基础知识 1.1 Java语言与面向对象的程序设计 1.1.1 面向对象的程序设计思想 1.1.2 Java语言的特点 1.1.3 Java类库 1.2 Java程序概述 1.2.1 Java开发环境 1.2.2 Application举例 1.2.3 ...
收入JAVA入门程序的案例,包括(JAVA语法基础,J2SE常用包,JAVA SWING 记忆JDBC连数据库技术)。这些例子非常容易理解,让能很快弄懂JAVA基础知识,对于入门者来说非常实用!
Java程序设计实用教程(第4版)[叶核亚][案例及素材],包含本书的全套源代码,绝对给力,学习java的朋友,绝对值得下载。对于有些同学,这些源代码可以用来做课程设计,例外对于本书配套的教学课件ppt,以及课后习题...
java 聊天程序 代码
Java is a popular and powerful language that is a virtual requirement for businesses making use of IT in their daily operations For Java programmers this reality offers job security and a wealth of ...
深入的讲解了java程序语言的基础知识,适应于初学者。