编写Java代码使java虚拟机崩溃

Posted

技术标签:

【中文标题】编写Java代码使java虚拟机崩溃【英文标题】:Write Java code to crash the java virtual machine 【发布时间】:2011-12-07 22:27:35 【问题描述】:

在我过去的一次采访中,有人要求我编写一个代码来使 JVM 崩溃。我说 System.exit()。它是否正确?有更好的答案吗?

澄清:我可以在开发和部署期间包含我的一段代码。并不是说 JVM 已经在运行,我必须编写一个黑客代码来使另一个 JVM 崩溃。

【问题讨论】:

不,这不会崩溃 VM。你可以通过无限循环轻松触发内存溢出。 System.exit() 只是终止 VM - 这是一个重复的问题 - 看这里 How do you crash a JVM? 我可以在开发过程中包含代码。 这个面试问题首先没有意义 是的,但是内存溢出是程序崩溃,而不是 VM 崩溃。要发生真正的 JVM 崩溃,您必须找到并使用实际的 JVM 错误 - 显然 JVM 崩溃不是正常预期运行时的一部分。 【参考方案1】:

您可以使用Unsafe 类,您可能猜到它使用起来不安全。

public static void main(String... args) throws Exception 
    getUnsafe().getByte(0);


private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException 
    Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
    theUnsafe.setAccessible(true);
    return (Unsafe) theUnsafe.get(null);

打印

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007ff1c2f23368, pid=2630, tid=140676351506176
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0-b17 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x82c368]  Unsafe_GetNativeByte+0xa8
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /nfs/peter/IdeaProjects/scratch/hs_err_pid2630.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

我用它来测试何时对文件进行了更改。我进行了更改并使 JVM 崩溃,以确保其他东西没有刷新或稍后出现。然后我检查我是否看到了预期的更新。

【讨论】:

使用 Unsafe 获得 SIGSEGV 的机会高于正常执行。 @Karussell 您更有可能获得 SIGBUS,除非您不小心访问了首页,而不是这样更好。 @Peter:您能分享一下Field 类的完全限定名称吗?在我的 Eclipse 工作区中执行 Ctrl+Shift+o 时,我得到了 11 个选项。 @PK' 在java.lang.reflect @Peter - 代码有效,但我无法看到 JVM 崩溃。在 Windows 8 x64 上使用 JDK1.7_u51。【参考方案2】:

我不认为礼貌地请求 JVM 终止真的算作“崩溃”。您必须确切地询问采访者他们所说的“崩溃”是什么意思。例如:

是否会强制堆栈溢出或内存不足条件计数? 您可以使用 JNI 或任何其他类型的本机代码吗? 告诉我您正在运行的确切 VM 版本,我会尝试查找 JIT 编译器错误...

(过去肯定存在 JIT 编译器问题 - 很久以前我有一个纯 Java 程序,它会始终出现段错误,但可以通过进行看起来像无操作更改的内容来“修复”。)

【讨论】:

【参考方案3】:

简单:要么用无限递归炸毁堆栈,要么用对象堆运行 JVM。

更复杂的是将 JVM 从内部堆中运行——您可能可以通过某种类加载循环来做到这一点,但这需要工作。

否则,您将不得不利用某种错误,或者至少使用 JNI。

public class Recur 
public static void main(String[] argv) 
    recur();

static void recur() 
    Object[] o = null;
    try 
        while(true) 
            Object[] newO = new Object[1];
            newO[0] = o;
            o = newO;
        
    
    finally 
        recur();
    



C:\JavaTools>java Recur
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6816, tid
=5432
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)

# Problematic frame:
# V  [jvm.dll+0x2e5c3d]
#
# An error report file with more information is saved as:
# C:\JavaTools\hs_err_pid6816.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

哒哒!!

(您可以限制对 Unsafe 的访问,但不能限制上述任何一个。)

【讨论】:

这只是Java栈或堆内存用完了,和JVM崩溃不一样。请参阅 Peter Lawrey 对 JVM 崩溃情况的回答。 “崩溃”的定义有些主观。 Unsafe 计划是我没有想到的。但是在内部堆之外运行 JVM 可能会导致“真正的”崩溃。 (请注意,JVM“通常”处理无限递归,只有一个未处理的异常关闭,但它高度依赖于上下文。)【参考方案4】:

要让整个计算机崩溃,我会这样做:

public static void crashComputer() 
    while(true) 
        Thread thread = new Thread(new Runnable() 
            @Override
            public void run() 
                while(true) 
                    crashComputer();
                
            
        );
        thread.start();
    


public static void crashJVM() 
    while(true)
        crashJVM();

crashComputer 函数大约需要 2 秒才能使整个计算机崩溃。您可以通过按住电源按钮来阻止它崩溃。

crashJVM函数通过堆栈重载,只使JVM崩溃,导致堆栈溢出(这就是本网站名称的由来)。

警告:使用风险自负。这不会损坏您的计算机,但如果您忘记单击文档或其他内容上的保存,我不会承担任何责任。

【讨论】:

【参考方案5】:

也可以使用 OutOfMemoryError 使应用程序崩溃。

public class StringOutOfMemory 
    public static void main(String[] args) 
        int i = 0;
        StringBuilder s = new StringBuilder("a");
        while (true) 
            s.append("ahgsdgjsdffsdfhsdgfsdfsdsfhdsgksdgkfgsdkfkdghfksdkfsdkfdkjfskdfkjsdfkdksdkdfjksjkhsdfjkfsdkjfsdhjkfsdjkfhdjkfkjsdfkjdsjkfd");
            System.out.println(i++); 
        
    

输出:

java.lang.OutOfMemoryError

【讨论】:

以上是关于编写Java代码使java虚拟机崩溃的主要内容,如果未能解决你的问题,请参考以下文章

深入理解java虚拟机

好书推荐—–深入理解Java虚拟机

JAVA - 深入JAVA 虚拟机 2

Java虚拟机JVM组成

Java虚拟机如何加载类,它又是如何实现一次编写到处执行?

如何分析,java 虚拟机异常崩溃 由系统捕获并生成的core文件