我们如何使JVM崩溃?

时间:2020-03-05 18:54:08  来源:igfitidea点击:

我正在读一本有关编程技能的书,作者问受访者:"如何崩溃JVM?"我认为我们可以通过编写一个无限的for循环来这样做,最终将耗尽所有内存。

有人有主意吗?

解决方案

回答

JNI。实际上,对于JNI,崩溃是默认的操作模式。我们必须付出更多的努力才能避免崩溃。

回答

取决于崩溃的含义。

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

我们还可以使用JNI调用本机代码。如果我们做的不正确,那么可能会使它崩溃。调试那些崩溃很"有趣"(相信我,我不得不编写一个很大的C ++ DLL,我们从一个已签名的Java applet中调用它)。 :)

回答

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

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

public void causeStackOverflow() {
    causeStackOverflow();
}

回答

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

回答

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

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

如果我们可以在VM的源代码中找到一个错误,并且例如在VM的实现的内存使用中引起分段错误,那么我们实际上可以将其崩溃。

回答

乔恩·迈耶(Jon Meyer)撰写的Java虚拟机一书中有一系列导致JVM进行核心转储的字节码指令示例。我找不到这本书的副本。如果外面有人,请查一下并发布答案。

回答

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

  • 使用JNI并在本机代码中崩溃。
  • 如果未安装安全管理器,则可以使用反射使VM崩溃。这是特定于VM的,但是通常VM会在私有字段中存储一堆指向本地资源的指针(例如,指向本地线程对象的指针存储在java.lang.Thread中的long字段中)。只需通过反射更改它们,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 *文件的真正崩溃。

回答

如果我们将崩溃定义为由于未处理的情况(即没有Java异常或者错误)而导致的流程中止,则无法从Java内部完成(除非我们有权使用sun.misc.Unsafe类)这就是托管代码的重点。

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

例如,JIT(生成的)代码,本机方法或者系统调用(图形驱动程序)可能会导致实际崩溃的问题(使用ZIP函数时崩溃很普遍,并且内存不足)。在这种情况下,JVM的崩溃处理程序将启动并转储状态。它还可以生成OS核心文件(Windows上为Watson博士,* nix上为核心转储)。

在Linux / Unix上,我们可以通过将信号发送给正在运行的进程来轻松地使JVM崩溃。注意:我们不应该为此使用SIGSEGV,因为Hotspot会捕获此信号并将其作为NullPointerException再次抛出。因此最好发送一个" SIGBUS"。

回答

在带有wmp10 jre6.0_7的winxpsp2上

Desktop.open(uriToAviOrMpgFile)

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

青年汽车

回答

这是有关导致JVM进行核心转储(即崩溃)的详细说明:
http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534

回答

我现在正在做,但是还不完全确定该怎么做... :-) JVM(和我的应用程序)有时会完全消失。没有引发任何错误,没有记录任何内容。从工作状态转变为完全不运行而没有任何警告。

回答

如果我们要假装内存不足,可以这样做

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

我知道几种通过调用本机方法(内置方法)导致JVM转储错误文件的方法,但最好的方法是我们不知道该怎么做。 ;)

回答

JNI是崩溃的主要来源。我们还可以使用JVMTI接口崩溃,因为该接口也需要用C / C ++编写。

回答

损坏的硬件可能会使任何程序崩溃。我曾经在特定计算机上可再现地崩溃了一个应用程序,而在其他计算机上却以完全相同的设置运行良好。原来这台机器的RAM有问题。

回答

用这个:

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:. Crash

回答

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

import sun.dc.pr.PathDasher; 

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