【问题标题】:Write Java code to crash the java virtual machine编写Java代码使java虚拟机崩溃
【发布时间】: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 崩溃不是正常预期运行时的一部分。

标签: java 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}}}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多