How to Crash Java VM
最近线上Java应用爆出了个很诡异的问题,需要理解Java虚拟机方面的知识,也正在补充JVM方面的知识;突然有个想法,如何人为的让JVM爆掉(Crash)呢?
这个想法说起来简单,实际上想考虑完全还是比较困难的。我将我自己想到的内容先放上来,后面会补充一些其它的知识。
1:利用JVM里面的一些非常规错误(Error),如StackOverflowError、OutOfMemoryError等。这个算是让虚拟机Crash的比较弱的条件,并不能算是JVM底层的问题,但是我们让JVM成功down掉了。
我们先看下StackOverflowError的情况:出现这种情况是因为虚拟机栈对于迭代深度有限制,当分配不足时,就会出现这个错误。
public class StackOverFlowCrash { /** * @param args */ public static void main ( String[] args ) { // TODO Auto-generated method stub main(args); } }
出现异常:Exception in thread "main" java.lang.StackOverflowError
该问题出现的原因是当调用函数时,会将这个函数信息放到这个线程的栈中,只要这个方法没有返回,这个栈就一直存在。如果方法的嵌套层次调用太多,导致超过栈设置大小,就产生StackOverflowError溢出异常。
实际上在使用栈空间不足时,都会产生这个StackOverflowError问题,如启用新线程时,如果栈空间不足就会出问题;或者在Native Method中申请超大内存时,也会产生这个Error问题。
public class OOMCrash { /** * @param args */ public static void main ( String[] args ) { // TODO Auto-generated method stub Object[] obj = new Object[Integer.MAX_VALUE]; } public static void stackOverflow(){ } }
Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
这个比较常见,就是申请的内存超过JVM的限制,就会导致OutOfMemoryError问题。
方法区内存溢出
方法区是用于存放Java的类相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等;在类加载器完成class文件加载的时候,会将这些信息放到方法区。如果方法区的内存占用达到最大值(-XX:MaxPermSize),就会抛出OOM异常,导致虚拟机Crash掉。
这种情况的测试思路比较简单,就是在运行区产生大量的类去填充方法区,直到方法区溢出为止。可以借助CGLib实现,动态生成类。
2:JNI方法
如果调用JNI方法时出现异常,或者JNI代码中Crash掉的话,JVM也会相应的Crash掉。
3:Security相关的Crash,使用反射可以调用JVM的本地方法资源,这样也可以导致JVM Crash掉。
import sun.misc.Unsafe; public class UnsafeCrash { /** * @param args */ private static final Unsafe unsafe = Unsafe.getUnsafe(); public static void crash() { unsafe.putAddress(0, 0); } public static void main(String[] args) { crash(); } }
执行后可以看下下面的异常,是SecurityException,同样会让JVM不能正常工作。
java.lang.ExceptionInInitializerError
Caused by: java.lang.SecurityException: Unsafe
3:JVM(Native Code) bug
JVM本身也是个应用,其代码也有bug,如果能找到jvm本身的bug,应该就能使得JVM Crash掉。
这里有个很经典的实例,利用了JVM本身的bug。
public class Crash { /** * @param args */ public static void main ( String[] args ) { Object[] o = null; while (true) { o = new Object[] {o}; } } }
执行后会产生一个JVM Crash掉的信息:
# # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dc3f414, pid=15928, tid=15708 # # JRE version: 6.0_20-b02 # Java VM: Java HotSpot(TM) 64-Bit Server VM (16.3-b01 mixed mode windows-amd64 ) # Problematic frame: # V [jvm.dll+0x3af414] # # An error report file with more information is saved as: # D:\workspace\jvmcrash\hs_err_pid15928.log
该bug问题比较严重,出现EXCEPTION_STACK_OVERFLOW提示,同时在应用目录下产生hs_err_pidXYZ.log。比较根本的原因是GC过程的栈信息出现Overflow问题,导致JVM Crash掉。该问题在1.6版本中存在,在1.7中出现了OOMError,并不会导致虚拟机本身出现问题,出现异常提示的原因也有不一样。
JVM的bug还可以看下这个实例:
import sun.dc.pr.PathDasher; public class PathDasherCrash { /** * @param args */ public static void main ( String[] args ) { PathDasher dasher = new PathDasher(null); } }
该方法执行后也会产生异常:
# # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006dab3975, pid=16500, tid=15796 # # JRE version: 6.0_20-b02 # Java VM: Java HotSpot(TM) 64-Bit Server VM (16.3-b01 mixed mode windows-amd64 ) # Problematic frame: # V [jvm.dll+0x223975] # # An error report file with more information is saved as: # D:\workspace\jvmcrash\hs_err_pid16500.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp #
注意是EXCEPTION_ACCESS_VIOLATION异常,这个异常的产生有多个方面的原因。
1:调用非安全方法
2:JVM对于传入参数的处理有问题
3:该类中的方法大部分是native方法,JVM调用的native方法中对于null参数的处理不正确。
根据以上的思路,JNI、Security Method、JVM bugs等方面都可以导致JVM不能正常运行。
不过导致的方法不一样,在Java中还有一些其它的表现如ByteBuffer的Direct内存分配超过限制、编译器bug(http://seanhe.iteye.com/blog/905997)等。
这个也算是从反向思路来学习Java Virtual Machine吧。在http://stackoverflow.com上有个关于这个话题的讨论,大家可以系统学习下,不过内容也不离本文;大家对于这个问题本身的讨论(JVM的Crash概念)比较有意思,这个可以仔细看下。
相关推荐
"Java Crash Course" contains a multitude of tips and tricks, examples and exercises you can do to grow your Java programming skills to unprecedented levels. We chose the content of this book carefully...
How to invoke Java web service in ASP
Java How to Program 11th edition英文版, 由EPUB转换而成, , 无密码保护,可复制文字 by Paul J. Deitel (Author), Harvey Deitel (Author)
java how to program 6th edition download java how to program 6th edition download
How to passthrough your integrated device to VM on ARM
Harvey M. Deitel, Paul J. Deitel-Java How to Program, 7th Edition-Prentice Hall (2007
Java How to Program (Early Objects) 9e contains an optional extensive OOD/UML 2 case study on developing and implementing the software for an automated teller machine.This edition covers both Java ...
Java How to Program, Early Objects, 11th Edition Java How to Program, Early Objects, 11th Edition Java How to Program, Early Objects, 11th Edition Java How to Program, Early Objects, 11th Edition
Java How to Program, Early Objects, 11th Edition, Deitel.pdf
教材是java how to program,这是第一二章的英文ppt课件
这个是合集~一般是这里最全的了 另外加的 PDF是英文的 .为 GCC4.1的HOWTO <br>目录 <br>ADSM-Backup-html<br>Advocacy<br>Automount-html<br>Battery-Powered-html<br>BootPrompt-HOWTO<br>Bridge-......
Think Java: How to Think Like a Computer Scientist by Allen B. Downey, Chris Mayfield 2016 | ISBN: 1491929561 Currently used at many colleges, universities, and high schools, this hands-on ...
The author is Paul Deitel, Oracle Java Champion, you can learn a lot about Java programming skill from this book.
How to invoke Java web service in ASP.net using C#.zip
Java大学教程(Java How to Program)(第四版)中文版[2].part2.rar 国外经典教程
Java How to Program(9th Edition) 超清晰pdf
Java How To Program 10th Late Objects Java大学教程第十版英文版,带书签,Late Objects版第七章介绍面向对象
Through Deitel & Associates, Inc., he has delivered Java, C, C++, C# and Visual Basic courses to industry clients, including IBM, Sun Microsystems, Dell, Lucent Technologies, Fidelity, NASA at the ...