当前位置:  开发笔记 > 编程语言 > 正文

你如何崩溃JVM?

如何解决《你如何崩溃JVM?》经验,为你挑选了15个好方法。

我正在读一本关于编程技巧的书,其中作者问受访者:"你如何崩溃JVM?" 我认为你可以通过编写一个最终耗尽所有内存的无限for循环来实现.

有人有什么想法吗?



1> ralfs..:

我不会调用抛出OutOfMemoryError或StackOverflowError崩溃.这些只是正常的例外.要真正崩溃VM有三种方法:

    使用JNI并在本机代码中崩溃.

    如果未安装任何安全管理器,则可以使用反射来崩溃VM.这是特定于VM的,但通常VM在私有字段中存储一串指向本机资源的指针(例如,指向本机线程对象的指针存储在java.lang.Thread中的长字段中).只需通过反射更改它们,VM迟早会崩溃.

    所有虚拟机都有错误,所以你只需触发一个.

对于最后一个方法,我有一个简短的例子,它会很好地破坏Sun Hotspot VM的安静:

public class Crash {
    public static void main(String[] args) {
        Object[] o = null;

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

这会导致GC中的堆栈溢出,因此您将不会获得StackOverflowError,而是包含hs_err*文件的真正崩溃.


哇!这会导致Sun Java 5,Sun Java 6和OpenJDK 6(在Ubuntu 9.04上)崩溃,没有hs_err*文件但只有"分段错误!" ...
不知道什么时候修复,但只是在1.7.0_09测试,它很好.刚刚得到预期:线程"main"中的异常java.lang.OutOfMemoryError:CrashJVM.main中的Java堆空间(CrashJVM.java:7)
在JDK 1.8_u71中,这会导致`java.lang.OutOfMemoryError:超出GC开销限制

2> Dan Dyer..:

JNI.事实上,对于JNI,崩溃是默认的操作模式.你必须加倍努力才能让它不会崩溃.


也许JNI的设计者听说过[崩溃专用软件](http://en.wikipedia.org/wiki/Crash-only_software),但还没有完全掌握这个想法.

3> Dave Griffit..:

用这个:

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();
    }
}

此类必须位于引导类路径中,因为它使用受信任的代码,因此运行如下:

java -Xbootclasspath/p:.紧急


您也可以这样做,而不是使用-Xbootclasspath:`Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); unsafe =(不安全)f.get(null);`对我很有用.

4> George Armho..:

我来到这里是因为我也在Chad Fowler的The Passionate Programmer中遇到了这个问题.对于那些无法访问副本的人来说,这个问题被视为一种过滤器/测试,用于面试需要"真正优秀的Java程序员"的职位的候选人.

具体来说,他问:

你会如何用纯Java编写一个会导致Java虚拟机崩溃的程序?

我用Java编程超过15年,我发现这个问题既困惑又不公平.正如其他人所指出的那样,Java作为一种托管语言,专门设计为不会崩溃.当然总有JVM错误,但是:

    经过15年以上的生产级JRE,这种情况很少见.

    任何这样的错误很可能会在下一个版本中修补,那么你作为程序员有多大可能遇到并回忆起当前JRE show-stoppers的细节?

正如其他人所提到的,通过JNI的一些本机代码是使JRE崩溃的可靠方法.但是作者在纯Java中特别提到,所以就这样了.

另一种选择是提供JRE伪字节码; 将一些垃圾二进制数据转储到.class文件很容易,并要求JRE运行它:

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

这算数了吗?我的意思是JRE本身并没有崩溃; 它正确检测到伪造的代码,报告并退出.

这给我们留下了最明显的解决方案,例如通过递归吹出堆栈,通过对象分配耗尽堆内存,或者简单地抛出RuntimeException.但这只会导致JRE以一个StackOverflowError或类似的异常退出,这也不是真正的崩溃.

那剩下什么了?我真的很想听听作者真正想到的是一个合适的解决方案.

更新:Chad Fowler 在这里回复.

PS:这是一本非常棒的书.在学习Ruby时,我选择了它以获得道德支持.



5> Rob Mayhew..:

此代码将以令人讨厌的方式崩溃JVM

import sun.dc.pr.PathDasher; 

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


这会在JDK 1.8中抛出一个`InternalError`.JVM不再失败.
截至1.6.0_29,这是唯一一个为我工作的人

6> Hot Licks..:

上次我试过这个会这样做:

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();
        }
    }
}

生成的日志文件的第一部分:

#
# 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



7> Dave L...:

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

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

如果您可以在VM的源代码中找到错误,例如导致VM实现的内存使用中出现分段错误,那么您实际上可能会崩溃它.



8> Prabath Siri..:

如果要使JVM崩溃 - 请在Sun JDK 1.6_23或更低版本中使用以下命令:

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

这是由于Sun JDK中的一个错误 - 也可以在OpenJDK中找到.这是从Oracle JDK 1.6_24开始修复的.



9> Herms..:

取决于崩溃的意思.

您可以进行无限递归以使其耗尽堆栈空间,但这会"优雅地"崩溃.你会得到一个例外,但JVM本身将处理所有事情.

您还可以使用JNI调用本机代码.如果你不这么做就可以让它崩溃.调试这些崩溃是"有趣的"(相信我,我必须编写一个我们从签名的java applet调用的大型C++ DLL).:)



10> Leigh Caldwe..:

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


没有适当的清理?你确定吗?文档说"通过启动其关闭序列来终止当前运行的Java虚拟机......所有已注册的关闭挂钩(如果有的话)都已启动...所有未经调查的终结器都在运行" - 这不是正确的清理吗?
这不会导致JVM崩溃,它有目的地明确地开始有序地关闭执行.
这真的是一个糟糕的答案.
更接近于崩溃jvm的是Runtime.getRuntime().halt(status).根据文档"这个方法不会导致关闭钩子被启动,并且如果已经启用了终止退出,则不会运行未经检查的终结器".仍然不是崩溃,但比System.exit更接近.

11> 小智..:

Jon Meyer的Java Virtual Machine一书中有一系列字节码指令的例子,这些指令导致JVM进行核心转储.我找不到这本书的副本.如果有人有,请查阅并发布答案.



12> 小智..:

在winxpsp2上w/wmp10 jre6.0_7

Desktop.open(uriToAviOrMpgFile)

这会导致生成的线程抛出未捕获的Throwable并崩溃热点

因人而异



13> Michael Borg..:

硬件损坏会导致任何程序崩溃.我曾经在特定的机器上重复出现应用程序崩溃,同时在其他机器上运行正常,具有完全相同的设置.事实证明该机器有错误的RAM.



14> RRM..:

最短的方式:)

public class Crash
{
    public static void main(String[] args)
    {
        main(args);
    }
}



15> henry..:

不是崩溃,而是比接受的使用答案更接​​近崩溃 System.exit

您可以通过调用来暂停JVM

Runtime.getRuntime().halt( status )

根据文件: -

"如果启用了finalization-on-exit,此方法不会导致启动关闭挂钩,也不会运行未启动的终结器".

推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有