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

  为了重现这个现象,我写了一个简单的例子。在本例中,先初始化了一个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. 移动端rem屏幕设置

    //修改页面title var pageTitle=document.getElementsByTagName("title")[0].innerHTML; if(location ...

  2. mysql中的数据类型长度

    “mysql中的数据类型长度是固定的 数据类型后面改的只是展示长度 没用的 int就是四个字节 2的31次方减一是最大值 所以改这个长度没用 只能改数据类型”

  3. 探索 Python + HyperLPR 进行车牌识别

    概要 HyperLRP是一个开源的.基于深度学习高性能中文车牌识别库,由北京智云视图科技有限公司开发,支持PHP.C/C++.Python语言,Windows/Mac/Linux/Android/IO ...

  4. c# 调用c++sdk时结构体与byte数组互转

    /// <summary> /// 由结构体转换为byte数组 /// </summary> public static byte[] StructureToByte<T ...

  5. JavaScript的技巧45招

    JavaScript奇技淫巧45招 来自仲老师的分享: 原文地址[http://chensd.com/2015-01/45-useful-javascript-tips-tricks-and-best ...

  6. flink整合kafka报错 WARN - Bootstrap broker ip:9092 disconnected

    WARN - The configuration 'zookeeper.connect' was supplied but isn't a known config.WARN - The config ...

  7. Spring Boot 缓存应用 Memcached 入门教程

    本章学习 Mmecached 在 Spring Boot 中的使用教程.Memcached 与 Redis 各有好处.本文主要学习 Spring Boot 中如何应用集成 Mmecached spri ...

  8. Java并发编程(四):并发容器(转)

    解决并发情况下的容器线程安全问题的.给多线程环境准备一个线程安全的容器对象. 线程安全的容器对象: Vector, Hashtable.线程安全容器对象,都是使用 synchronized 方法实现的 ...

  9. Flask - flask-mail

    flasky中git reset --hard 8e 问题 使用flask-mail通过163邮箱的smtp服务发送token认证邮件,要关闭TLS才能发送 原理 还在研究中 结果

  10. Unity - 求反射向量 (2d)

    求反射向量 https://www.cnblogs.com/graphics/archive/2013/02/21/2920627.html 上面是大佬的公式可以去看一下 借的大佬的图 1.求入射向量 ...