我们如何使JVM崩溃?
我正在读一本有关编程技能的书,作者问受访者:"如何崩溃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) ; } }