今天花了一整天在跟踪一个问题,每次感觉已经快找到原因的时候发现现象又变了,我觉得从中吸取的教训可以给大家分享一下。

  为了重现这个现象,我写了一个简单的例子。在本例中,先初始化了一个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"

  这说明了什么?当资源紧缺的时候,你根本没法判断你的应用程序是怎么挂掉的,因此不要指望能出现你所预期的一系列错误提示。从上面这个例子中可以看到,你的程序可能会以三种完全不同的方式挂掉:

  GC的安全性检查失败:一旦GC花费的时间占到98%以上的话,JVM就会宣告投降了: java.lang.OutOfMemoryError: GC overhead limit exceeded.

  无法为下一个操作分配足够的内存:如果无法满足下一条指令所需要分配的内存的话,你会收到一条"java.lang.OutOfMemoryError: Java heap space" 的错误信息。

  你可能也总结出来了,还有一种情况是你的内存已经紧张到连JVM创建一条OutOfMemoryError异常,填充堆栈信息,打印到屏幕上这点要求都满足不了了。这种情况UncaughtExceptionHandler会捕获到这个错误,而不再走通常的错误流程。这个处理器恰如其名,当线程由于某个异常快要挂掉的时候,它开始出来收场了。出现这种情况的话,JVM会找到线程对应的 UncaughtExceptionHandler,然后调用它的uncaughtException方法。

  因此当你捕获到内存不足的异常并自以为已经胸有成竹时,请再多思考一下 .系统已经处于崩溃的边缘,你原认为你能依赖的信息很可能会消失或者改变。留给你的只有一脸茫然,正如我前面那12个小时中那样。

  如果你已经耐心读到这了,我推荐你关注下我们的twitter帐号。我们每周都会发一些工作中碰到的一些性能调优的问题。

Java程序挂掉的几种可能的更多相关文章

  1. java程序死锁,3种方式快速找到死锁代码

    java程序中出现死锁问题,如果不了解排查方法,是束手无策的,今天咱们用三种方法找到死锁问题. 运行下面代码 package com.jvm.visualvm; /** * <a href=&q ...

  2. 检测Java程序运行时间的2种方法(高精度的时间[纳秒]与低精度的时间[毫秒])

    第一种是以毫秒为单位计算的. 代码如下: long startTime=System.currentTimeMillis(); //获取开始时间 doSomeThing(); //测试的代码段 lon ...

  3. Java程序员

    从生存.制胜.发展三个方面入手,为大家展示出程序员求职与工作的一幅3D全景图像.本书中既有在公司中的生存技巧,又有高手达人的进阶策略,既有求职攻略的按图索骥,又有入职后生产环境的破解揭秘. 书中浓缩了 ...

  4. Java程序语言的后门-反射机制

    在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...

  5. 003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程

    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程 Java程序长啥样? 首先编写一个Java程序 记事本编写程序 打开记事本 1.wi ...

  6. redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)

    平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...

  7. Java程序员的现代RPC指南(Windows版预编译好的Protoc支持C++,Java,Python三种最常用的语言,Thrift则支持几乎主流的各种语言)

    Java程序员的现代RPC指南 1.前言 1.1 RPC框架简介 最早接触RPC还是初学Java时,直接用Socket API传东西好麻烦.于是发现了JDK直接支持的RMI,然后就用得不亦乐乎,各种大 ...

  8. 【Java程序】tesseract_orc java上的一种实现方法

    今天想着把以前做过的一个Android的文字检测识别应用好好的回顾一下,因为以前写java程序,目的就是能用就行,不会仔细看每一个部分代码,也不会记他们的用法,不回会去查API,借鉴别人的例程,用过就 ...

  9. 一个简单的Java程序例子以及其几种注释

    在说道主题前,先来啰嗦两句,o()︿︶)o 唉,不说两句心里就有个疙瘩,也许这就是所谓的强迫症吧,好了说说我想啰嗦的,其实也就是这样子的,关于Java开发工具箱的下载以及环境的配置.Java开发工具箱 ...

随机推荐

  1. 如何重启Cisco LAP?

    在Cisco WLC上进入对应的AP,能够看到Reset这个AP,但是这里会有两种选择: 看到上述的描述,可能很多人都不敢轻易的操作: 1.Hardware Reset:Perform a hardw ...

  2. Android学习02

    今天学了ScrollView&HorizontalScrollView和WebView 一.ScrollView(垂直滚动),HorizontalScrollView(水平滚动) Scroll ...

  3. Jmeter_正则表达式提取器_提取数组 & For Each 控制器

    1.举例: https://demodaojia.ecjia.com/ 提取黄色标注的这些内容 2. 3. 匹配数字:-1 表示匹配全部,0表示随机一个 4. 5.我们获取了10组数据,通过正则提取器 ...

  4. 【struts 报错】 No action config found for the specified url

    1 type Exception report message org.apache.struts.chain.commands.InvalidPathException: No action con ...

  5. Steam 游戏 《Sudoku Universe(数独宇宙)》、《Sudoku Killer(数独杀手)》、《Sudoku Jigsaw(数独拼图)》数字位置解析 ---------C# 数独程序解析(2020年寒假小目标11)

    日期:2020.02.11 博客期:151 星期二 今天,准备肝一个 C# 的数独读写工具(汇编语言也在努力学习命令方法中...),这三个游戏我早就买下了,一直放在 Steam 库里积灰,看着它的成就 ...

  6. c#本地缓存当数据库表更改时,缓存失效。

    web.config <?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 ASP.NET 应 ...

  7. Django框架之模板语言特殊标记(将后端的数据显示到前端)

    后端代码 def GetMain(request): return render( request, "main.html", { "user1":" ...

  8. idea 创建maven子父工程

    1.创建maven工程: 2. 创建工程名称: 3.删除父工程下的src文件夹,指定打包方式为pom,添加maven依赖: 4.右键项目添加子工程: 5.添加子工程名称: 6.子工程创建成功: 7.依 ...

  9. java获取tomcat中的properties文件

    System.getProperty("catalina.home") 获取tomcat的绝对路径 获取文件的绝对路径 在windous中拼接路径是" \ " ...

  10. ISE主备注册和同步

    Synchronize Primary and Secondary Cisco ISE Nodes You can make configuration changes to Cisco ISE on ...