我在读一本关于编程技巧的书,在书中作者问被采访者,"你是如何使一个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 >