如何使Java虛擬機器崩潰
最初見到這個問題是在《我程式設計,我快樂——程式設計師職業規劃之道》上,我的第一反應是構造一個OutOfMemoryError或者StackOverflowError。為了快速產生結果,在JVM引數進行如下設定後:
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
下面的程式碼即可很快產生OutOfMemoryError:
import java.util.ArrayList;
import java.util.List;
public class Crash {
public static void main(String[] args) {
List<Object> list = new ArrayList<Object>();
while(true) {
list.add(new Object());
}
}
}
輸出效果
[GC (Allocation Failure) [PSYoungGen: 7330K->992K(9216K)] 7330K->5297K(19456K), 0.0094021 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) --[PSYoungGen: 9184K->9184K(9216K)] 13489K->19416K(19456K), 0.0171858 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]
[Full GC (Ergonomics) [PSYoungGen: 9184K->0K(9216K)] [ParOldGen: 10232K->9893K(10240K)] 19416K->9893K(19456K), [Metaspace: 2524K->2524K(1056768K)], 0.1437797 secs] [Times: user=0.23 sys=0.00, real=0.14 secs]
[Full GC (Ergonomics) [PSYoungGen: 7706K->8077K(9216K)] [ParOldGen: 9893K->7783K(10240K)] 17600K->15860K(19456K), [Metaspace: 2524K->2524K(1056768K)], 0.1274782 secs] [Times: user=0.25 sys=0.00, real=0.13 secs]
[Full GC (Allocation Failure) [PSYoungGen: 8077K->8076K(9216K)] [ParOldGen: 7783K->7783K(10240K)] 15860K->15859K(19456K), [Metaspace: 2524K->2524K(1056768K)], 0.0685814 secs] [Times: user=0.16 sys=0.00, real=0.07 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at Demo.main(Demo.java:9)
[Full GC (Ergonomics) [PSYoungGen: 8192K->0K(9216K)] [ParOldGen: 7783K->492K(10240K)] 15975K->492K(19456K), [Metaspace: 2550K->2550K(1056768K)], 0.0036032 secs] [Times: user=0.06 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 164K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 2% used [0x00000000ff600000,0x00000000ff6290e8,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 492K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 4% used [0x00000000fec00000,0x00000000fec7b000,0x00000000ff600000)
Metaspace used 2557K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 275K, capacity 386K, committed 512K, reserved 1048576K
至於產生StackOverflowError,一個沒有返回的遞迴函式即可實現。
但從某種意義上說,這些並沒有讓JVM崩潰,而是丟擲一個異常,Java虛擬機器規範裡面已經明確定義了這些異常發生的情況。
在真正的黑客眼裡,JVM內部的Bug才是他們的答案。但JVM內部的Bug最終會被修復,對於一般愛好者,可以找找以前的Java Bug Database,然後用舊版本的JVM驗證。
不過還有另外一種容易引起JVM崩潰的地方就是JNI,雖然是外部程式碼引起的,但應該也算是JVM機制上的一種缺陷吧。
以下演示一下JNI導致Java虛擬機器崩潰的例子。語文學得不好,直接上程式碼:
JvmCrash.java
class JvmCrash
{
public static native void greeting();
}
JvmCrashTest.java
class JvmCrashTest
{
public static void main(String[] args)
{
JvmCrash.greeting();
}
static
{
System.loadLibrary("JvmCrash");
}
}
JvmCrash.h (由javah工具自動生成的)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JvmCrash */
#ifndef _Included_JvmCrash
#define _Included_JvmCrash
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JvmCrash
* Method: greeting
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JvmCrash_greeting
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
JvmCrash.c
#include "JvmCrash.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_JvmCrash_greeting(JNIEnv* env, jclass cl)
{
printf("Hello Crash World!\n");
int i = 0;
int j = 1 / i;
}
然後,我們就能得到一個Fatal Error而不是一個Exception了!
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_INT_DIVIDE_BY_ZERO (0xc0000094) at pc=0x10001020, pid=2388, tid=4988
#
# JRE version: Java(TM) SE Runtime Environment (8.0_40-b26) (build 1.8.0_40-b26)
# Java VM: Java HotSpot(TM) Client VM (25.40-b25 mixed mode, sharing windows-x86 )
# Problematic frame:
# C [JvmCrash.dll+0x1020]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Documents and Settings\Administrator\workspace\JNICrash\hs_err_pid2388.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Hello Crash World!
相關文章
- Dalvik虛擬機器、Java虛擬機器與ART虛擬機器虛擬機Java
- java虛擬機器和Dalvik虛擬機器Java虛擬機
- Android 虛擬機器 Vs Java 虛擬機器Android虛擬機Java
- 克隆虛擬機器後,使兩臺虛擬機器完全獨立需要更改的配置。虛擬機
- 一次虛擬機器 (virtual box + vagrant + homestead) 崩潰與 debug 的過程虛擬機
- Java虛擬機器(JVM)Java虛擬機JVM
- Java虛擬機器(轉)Java虛擬機
- Java 虛擬機器之三:Java虛擬機器的記憶體結構Java虛擬機記憶體
- 備戰- Java虛擬機器Java虛擬機
- Java虛擬機器16:MetaspaceJava虛擬機
- Java虛擬機器面試題Java虛擬機面試題
- .Net框架 = Java虛擬機器?框架Java虛擬機
- java~graalVM虛擬機器JavaLVM虛擬機
- VMware虛擬機器如何設定使主機和虛擬機器不同IP虛擬機
- Java基礎:Java虛擬機器(JVM)Java虛擬機JVM
- Java虛擬機器 —— 垃圾回收機制Java虛擬機
- 詳解Java 虛擬機器(第②篇)——HotSpot 虛擬機器物件Java虛擬機HotSpot物件
- 《深入理解java虛擬機器》學習筆記4——Java虛擬機器垃圾收集器Java虛擬機筆記
- 深入理解java虛擬機器Java虛擬機
- java虛擬機器指令常量部分Java虛擬機
- Java 虛擬機器診斷利器Java虛擬機
- Java虛擬機器的組成Java虛擬機
- Java虛擬機器是什麼?Java虛擬機
- 深入學習Java虛擬機器——虛擬機器位元組碼執行引擎Java虛擬機
- Java虛擬機器8:虛擬機器效能監控與故障處理工具Java虛擬機
- 《深入理解Java虛擬機器》個人讀書總結——JAVA虛擬機器記憶體Java虛擬機記憶體
- Java JVM——5.Java虛擬機器棧JavaJVM虛擬機
- Java虛擬機器1:什麼是JavaJava虛擬機
- java虛擬機器類載入機制Java虛擬機
- Java 虛擬機器類載入機制Java虛擬機
- Java虛擬機器04——垃圾收集器Java虛擬機
- Java虛擬機器10:類載入器Java虛擬機
- Java虛擬機器9:Java類載入機制Java虛擬機
- 深入理解Java虛擬機器8 虛擬機器位元組碼執行引擎Java虛擬機
- 《深入理解java虛擬機器》學習筆記7——Java虛擬機器類生命週期Java虛擬機筆記
- 虛擬機器虛擬機
- WkWebView 令人崩潰的崩潰WebView
- 深入理解Java虛擬機器(一)Java虛擬機