I was reading a book on programming skills wherein the author asks the interviewee, "How do you crash a JVM?" I thought that you could do so by writing an infinite for-loop that would eventually use up all the memory.
Anybody has any idea?
Try running the application without the YJP agent to see if you can still reproduce the crash. Generally, JVM crashes are pretty hard to diagnose. They could happen due to a bug in some JNI code or in the JRE itself. If you suspect the latter, it may be worth submitting a bug report to Oracle.
Common causes of JVM Crash Running out of native memory. This is caused when native memory is exhausted, read more about native memory allocation here. Segmentation faults. These are caused by a program trying to read or write an illegal memory location.
Viewing Java Virtual Machine crash logs JVM crash log files are named hs_err_pid*. log, with the process id of the JVM that crashed, and are placed in the Micro-Manager folder.
Reduce the Java heap size. The Java heap is only a certain part of the total memory used by the JVM. If the Java heap is significantly larger, JVM can run out of virtual memory while compiling methods or when native libraries are loaded. Try lowering the maximum heap size to avoid this error.
I wouldn't call throwing an OutOfMemoryError or StackOverflowError a crash. These are just normal exceptions. To really crash a VM there are 3 ways:
For the last method I have a short example, which will crash a Sun Hotspot VM quiet nicely:
public class Crash {
public static void main(String[] args) {
Object[] o = null;
while (true) {
o = new Object[] {o};
}
}
}
This leads to a stack overflow in the GC so you will get no StackOverflowError but a real crash including a hs_err* file.
JNI. In fact, with JNI, crashing is the default mode of operation. You have to work extra hard to get it not to crash.
Use this:
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();
}
}
This class must be on the boot classpath because it is using trusted code,so run like this:
java -Xbootclasspath/p:. Crash
EDIT: Simplified version with pushy's suggestion:
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
unsafe.putAddress(0, 0);
I came here because I also ran into this question in The Passionate Programmer, by Chad Fowler. For those who don't have access to a copy, the question is framed as a kind of filter/test for candidates interviewing for a position requiring "really good Java programmers."
Specifically, he asks:
How would you write a program, in pure Java, that would cause the Java Virtual Machine to crash?
I've programmed in Java for over 15 years, and I found this question to be both puzzling and unfair. As others have pointed out, Java, as a managed language, is specifically designed not to crash. Of course there are always JVM bugs, but:
As others have mentioned, some native code via JNI is a sure way to crash a JRE. But the author specifically mentioned in pure Java, so that's out.
Another option would be to feed the JRE bogus byte codes; it's easy enough to dump some garbage binary data to a .class file, and ask the JRE to run it:
$ echo 'crap crap crap' > crap.class
$ java crap
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap
Does that count? I mean the JRE itself hasn't crashed; it properly detected the bogus code, reported it, and exited.
This leaves us with the most obvious kinds of solutions such as blowing the stack via recursion, running out of heap memory via object allocations, or simply throwing RuntimeException
. But this just causes the JRE to exit with a StackOverflowError
or similar exception, which, again is not really a crash.
So what's left? I'd really love to hear what the author really had in mind as a proper solution.
Update: Chad Fowler responded here.
PS: it's an otherwise great book. I picked it up for moral support while learning Ruby.
Last time I tried this would do it:
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();
}
}
}
First part of generated log file:
#
# 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
This code will crash the JVM in nasty ways
import sun.dc.pr.PathDasher;
public class Crash
{
public static void main(String[] args)
{
PathDasher dasher = new PathDasher(null) ;
}
}
A perfect JVM implementation will never crash.
To crash a JVM, aside from JNI, you need to find a bug in the VM itself. An infinite loop just consumes CPU. Infinitely allocating memory should just cause OutOfMemoryError's in a well built JVM. This would probably cause problems for other threads, but a good JVM still should not crash.
If you can find a bug in the source code of the VM, and for example cause a segmentation fault in the memory usage of the implementation of the VM, then you can actually crash it.
If you want to crash JVM - use the following in Sun JDK 1.6_23 or below:
Double.parseDouble("2.2250738585072012e-308");
This is due to a bug in Sun JDK - also found in OpenJDK. This is fixed from Oracle JDK 1.6_24 onwards.
Depends on what you mean by crash.
You can do an infinite recursion to make it run out of stack space, but that'll crash "gracefully". You'll get an exception, but the JVM itself will be handling everything.
You can also use JNI to call native code. If you don't do it just right then you can make it crash hard. Debugging those crashes is "fun" (trust me, I had to write a big C++ DLL that we call from a signed java applet). :)
The closest thing to a single "answer" is System.exit()
which terminates the JVM immediately without proper cleanup. But apart from that, native code and resource exhaustion are the most likely answers. Alternatively you can go looking on Sun's bug tracker for bugs in your version of the JVM, some of which allow for repeatable crash scenarios. We used to get semi-regular crashes when approaching the 4 Gb memory limit under the 32-bit versions (we generally use 64-bit now).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With