关于java:你如何崩溃JVM?

关于java:你如何崩溃JVM?

How do you crash a JVM?

我在读一本关于编程技巧的书,在书中作者问被采访者,"你是如何使一个JVM崩溃的?"我想你可以通过编写一个无限的for循环来做到这一点,最终会耗尽所有的内存。

有人知道吗?


我不会称抛出OutOfMemoryError或StackOverflowError为崩溃。这些只是正常的例外。要使虚拟机真正崩溃,有三种方法:

  • 使用JNI并在本机代码中崩溃。
  • 如果没有安装安全管理器,您可以使用反射来崩溃虚拟机。这是特定于VM的,但通常VM在私有字段中存储一组指向本地资源的指针(例如,指向本地线程对象的指针存储在Java.Lang.Trm的长字段中)。只要通过反射改变它们,虚拟机迟早会崩溃。
  • 所有的虚拟机都有错误,所以你只需要触发一个。
  • 对于最后一个方法,我有一个简短的示例,它可以很好地使Sun Hotspot VM崩溃:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Crash {
        public static void main(String[] args) {
            Object[] o = null;

            while (true) {
                o = new Object[] {o};
            }
        }
    }

    这会导致GC中的堆栈溢出,因此您将不会得到StackOverflowError,而是会遇到包括hs_err*文件在内的真正崩溃。


    JNI。实际上,对于JNI,崩溃是默认的操作模式。你必须加倍努力才能使它不致崩溃。


    本:使用 </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import sun.misc.Unsafe;

    public class Crash {
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        public static void crash() {
            unsafe.putAddress(0, 0);
        }
        public static void main(String[] args) {
            crash();
        }
    }

    这是一级的黑启动路径,因为它是用代码运行的信任,所以这类: </P >

    java -Xbootclasspath/p:. Crash


    我在这里跑了,因为我也在为这个问题passionate programmer,由乍得福勒。为那些谁不有接入到一个拷贝的问题是,作为一类的过滤器/构试验的候选interviewing为一位"Java programmers requiring真的好。" </P >

    specifically,他asks: </P >

    How would you write a program, in pure Java, that would cause the Java Virtual Machine to crash?

    我已经在Java的程序升温方法过了十五年,我发现这个问题都被puzzling和unfair。要为他人的pointed门诊,Java语言作为一managed自行设计的,在不到specifically崩溃。大学课程是永远的JVM有错误,但是: </P >

  • 售后服务部+年生产15级的JRE,这是非常罕见的。
  • 任何这样的错误是在下一patched likely被释放,所以如何likely你作为一个programmer运行和对细节的recall成的流系集stoppers LRU的节目吗?
  • 如有上述一些本土人,通过JNI代码是一个死的方式对一个LRU的崩溃。但在上述的作者specifically纯Java的,所以这样的情况。 </P >

    另一选择将是对饲料的LRU bogus字节的代码;它的容易够到把二进制数据到一个.class一些垃圾文件,运行它的LRU和问到: </P >

    1
    2
    3
    $ echo 'crap crap crap' > crap.class
    $ java crap
    Exception in thread"main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap

    有这个数?I T均在JRE本身还没有crashed;它的detected这份报告的bogus代码,它和exited。 </P >

    本种的叶部与美国最明显的解决方案是在这样的blowing通过递归的运行栈,出的堆分配存储器通过面向普throwing RuntimeException,或。。。。。。。但这只是causes LRU的对境与一个或StackOverflowErrorEXCEPTION相似,这一次,真的是不一的崩溃。 </P >

    所以叫什么来的?我会听到什么,作者对《真的爱真的有在我作为一个正确的解决方案。 </P >

    更新:Chad Fowler responded这里。 </P >

    PS:它的一个伟大的书,否则。。。。。。。它在道德上的支持,而屈体的方法学习Ruby。 </P >


    将这个代码的JVM崩溃在讨厌的方法 </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import sun.dc.pr.PathDasher;

    public class Crash
    {
         public static void main(String[] args)
         {    
            PathDasher dasher = new PathDasher(null) ;
         }
    }

    我的孩子tried时这将做它: </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Recur {
        public static void main(String[] argv) {
            try {
                recur();
            }
            catch (Error e) {
                System.out.println(e.toString());
            }
            System.out.println("Ended normally");
        }
        static void recur() {
            Object[] o = null;
            try {
                while(true) {
                    Object[] newO = new Object[1];
                    newO[0] = o;
                    o = newO;
                }
            }
            finally {
                recur();
            }
        }
    }

    第一部分产生的日志文件: </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #
    # An unexpected error has been detected by Java Runtime Environment:
    #
    #  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996
    #
    # Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)
    # Problematic frame:
    # V  [jvm.dll+0x2e5c3d]
    #
    # If you would like to submit a bug report, please visit:
    #   http://java.sun.com/webapps/bugreport/crash.jsp
    #

    ---------------  T H R E A D  ---------------

    Current thread (0x00000000014c6000):  VMThread [stack: 0x0000000049810000,0x0000000049910000] [id=1996]

    siginfo: ExceptionCode=0xc00000fd, ExceptionInformation=0x0000000000000001 0x0000000049813fe8

    Registers:
    EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400
    ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400
    EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206

    完美的JVM实现永远不会崩溃。

    要使JVM崩溃,除了JNI之外,还需要在VM本身中找到一个bug。无限循环只消耗CPU。无限分配内存只会导致构建良好的JVM中出现内存不足错误。这可能会给其他线程带来问题,但是一个好的JVM仍然不应该崩溃。

    如果您可以在虚拟机的源代码中找到一个bug,例如,在虚拟机实现的内存使用中导致一个分段错误,那么您实际上可以使它崩溃。


    如果你想使用的Java虚拟机崩溃在太阳下面的JDK 1.6 _或小于23: </P >

    1
    Double.parseDouble("2.2250738585072012e-308");

    这是由于到一个错误在Sun JDK -也发现在openjdk。 这是从Oracle的定点_ 24 onwards JDK 1.6。 </P >


    取决于你所说的撞车是什么意思。

    您可以执行无限递归,使其耗尽堆栈空间,但这将"优雅地"崩溃。您将得到一个异常,但JVM本身将处理所有事情。

    也可以使用JNI调用本机代码。如果你不做得恰到好处,那么你可以让它很难崩溃。调试这些崩溃是"有趣的"(相信我,我必须写一个大的C++ DLL,我们从一个签名的Java applet调用)。:)


    Jon Meyer的JAVA虚拟机有一系列字节码指令的例子,这些指令导致JVM成为核心转储。我找不到这本书的副本。如果外面有人有,请查一下并把答案贴出来。


    最接近单个"答案"的是System.exit(),它在没有适当清理的情况下立即终止JVM。但除此之外,本地代码和资源耗尽是最可能的答案。或者,您可以在Sun的bug跟踪器上查找您的JVM版本中的bug,其中一些版本允许重复的崩溃场景。在32位版本(现在我们通常使用64位)下,当接近4GB内存限制时,我们通常会遇到半常规崩溃。


    shortest)尽可能的方式: </P >

    1
    2
    3
    4
    5
    6
    7
    public class Crash
    {
        public static void main(String[] args)
        {
            main(args);
        }
    }

    任何程序可以破五金的崩溃。有一次我的应用程序的崩溃是一reproducably特异性,而其他机器的运行机制与精细的setup一样精确。这机器有turns门诊faulty RAM。 </P >


    是winxpsp2 W / wmp10 jre6.0 _ 7 </P >

    desktop.open(uritoaviormpgfile) </P >

    这一causes spawned线对throw安crashes hotspot)和未被发现的 </P >

    ymmv </P >


    但不到一个closer的崩溃,崩溃的答案比这里利用System.exit </P >

    你可以停止在JVM中呼唤 </P >

    Runtime.getRuntime().halt( status ) </P >

    根据《文档: </P >

    "this method does not cause shutdown hooks to be started and does not run uninvoked finalizers if finalization-on-exit has been enabled".


    如果将崩溃定义为进程中止,因为未处理的情况(即没有Java异常或错误),那么这不能从Java内部完成(除非您有权限使用Sun.MISC不安全类)。这就是托管代码的全部要点。

    本机代码中的典型崩溃是通过取消引用指向错误内存区域(空地址或错误对齐)的指针而发生的。另一个来源可能是非法的机器指令(操作码)或来自库或内核调用的未处理信号。如果JVM或系统库中有bug,则两者都可以触发。

    例如,jitted(生成)代码、本机方法或系统调用(图形驱动程序)可能会出现导致实际崩溃的问题(使用zip函数而内存不足时,很常见会发生崩溃)。在这些情况下,JVM的崩溃处理程序将启动并转储状态。它还可以生成一个操作系统核心文件(Windows上的Watson博士和*nix上的core dump)。

    在Linux/Unix上,通过向正在运行的进程发送信号,您可以轻松地使JVM崩溃。注意:您不应该对此使用SIGSEGV,因为Hotspot捕捉到该信号,并在大多数地方将其作为nullPointerException重新抛出。因此,最好发送一个SIGBUS


    这里是一个详细的解释了什么是核心dump(即今天causes JVM崩溃): http:/ / / / viewcontent.do kb.adobe.com自动化?externalid TN = _ 17534 </P >


    JNI是一个大crashes来源。你可以使用接口的jvmti崩溃也从那被需求的书面在C / C + +为好。 </P >


    如果你想对你要运行的内存pretend出你能做的 </P >

    1
    2
    3
    public static void main(String[] args) {
        throw new OutOfmemoryError();
    }

    我知道一对夫妇的方式,因为JVM dump文件中的一个本地方法误差的呼唤,这是定制的,但它可能在你不知道如何最好的去做这个。); </P >


    如果您创建一个线程进程,它无限地生成更多的线程(这将生成更多的线程,这…),那么最终会在JVM本身中导致堆栈溢出错误。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Crash {
        public static void main(String[] args) {

            Runnable[] arr = new Runnable[1];
            arr[0] = () -> {

                while (true) {
                    new Thread(arr[0]).start();
                }
            };

            arr[0].run();
        }
    }

    这给了我输出(5分钟后,注意你的内存)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    An unrecoverable stack overflow has occurred.
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078
    #
    # JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
    # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
    # Problematic frame:
    #

    shortest???????对机器人的使用Ctrl +级触发开关。当我发现这对我是trying Close My不闭合(控制台程序,它有好的"境"functionality)。 </P >


    我现在做它,但不entirely怎么死的…………………Java虚拟机(-):有时和我的应用程序是完全disappear)。嗯,thrown logged错误,一无所有。爱情不是从工作到运行在instantly与NO的预警。 </P >


    这算吗?

    1
    2
    long pid = ProcessHandle.current().pid();
    try { Runtime.getRuntime().exec("kill -9"+pid); } catch (Exception e) {}

    它只适用于Linux和Java 9。

    由于某种原因,我不明白,ProcessHandle.current().destroyForcibly();不杀死JVM,抛出java.lang.IllegalStateException,不允许破坏当前进程的消息。


    如果将无限for循环更改为对同一函数的递归调用,则会出现堆栈溢出异常:

    1
    2
    3
    4
    5
    6
    7
    public static void main(String[] args) {
        causeStackOverflow();
    }

    public void causeStackOverflow() {
        causeStackOverflow();
    }


    如果一个崩溃的那是什么interrupts JVM /程序从正规termination安,当时的联合国handled EXCEPTION能做这个。 </P >

    1
    2
    3
    4
    public static void main(String args[]){
       int i = 1/0;
       System.out.print(i); // This part will not be executed due to above  unhandled exception
      }

    所以,它是什么depends type of崩溃?!!!!!!! </P >


    推荐阅读