编写Java代码使java虚拟机崩溃
Posted
技术标签:
【中文标题】编写Java代码使java虚拟机崩溃【英文标题】:Write Java code to crash the java virtual machine 【发布时间】:2011-12-07 22:27:35 【问题描述】:在我过去的一次采访中,有人要求我编写一个代码来使 JVM 崩溃。我说 System.exit()。它是否正确?有更好的答案吗?
澄清:我可以在开发和部署期间包含我的一段代码。并不是说 JVM 已经在运行,我必须编写一个黑客代码来使另一个 JVM 崩溃。
【问题讨论】:
不,这不会崩溃 VM。你可以通过无限循环轻松触发内存溢出。System.exit()
只是终止 VM - 这是一个重复的问题 - 看这里 How do you crash a JVM?
我可以在开发过程中包含代码。
这个面试问题首先没有意义!
是的,但是内存溢出是程序崩溃,而不是 VM 崩溃。要发生真正的 JVM 崩溃,您必须找到并使用实际的 JVM 错误 - 显然 JVM 崩溃不是正常预期运行时的一部分。
【参考方案1】:
您可以使用Unsafe
类,您可能猜到它使用起来不安全。
public static void main(String... args) throws Exception
getUnsafe().getByte(0);
private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
打印
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007ff1c2f23368, pid=2630, tid=140676351506176
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0-b17 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x82c368] Unsafe_GetNativeByte+0xa8
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /nfs/peter/IdeaProjects/scratch/hs_err_pid2630.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
#
我用它来测试何时对文件进行了更改。我进行了更改并使 JVM 崩溃,以确保其他东西没有刷新或稍后出现。然后我检查我是否看到了预期的更新。
【讨论】:
使用 Unsafe 获得 SIGSEGV 的机会高于正常执行。 @Karussell 您更有可能获得 SIGBUS,除非您不小心访问了首页,而不是这样更好。 @Peter:您能分享一下Field
类的完全限定名称吗?在我的 Eclipse 工作区中执行 Ctrl+Shift+o 时,我得到了 11 个选项。
@PK' 在java.lang.reflect
@Peter - 代码有效,但我无法看到 JVM 崩溃。在 Windows 8 x64 上使用 JDK1.7_u51。【参考方案2】:
我不认为礼貌地请求 JVM 终止真的算作“崩溃”。您必须确切地询问采访者他们所说的“崩溃”是什么意思。例如:
是否会强制堆栈溢出或内存不足条件计数? 您可以使用 JNI 或任何其他类型的本机代码吗? 告诉我您正在运行的确切 VM 版本,我会尝试查找 JIT 编译器错误...(过去肯定存在 JIT 编译器问题 - 很久以前我有一个纯 Java 程序,它会始终出现段错误,但可以通过进行看起来像无操作更改的内容来“修复”。)
【讨论】:
【参考方案3】:简单:要么用无限递归炸毁堆栈,要么用对象堆运行 JVM。
更复杂的是将 JVM 从内部堆中运行——您可能可以通过某种类加载循环来做到这一点,但这需要工作。
否则,您将不得不利用某种错误,或者至少使用 JNI。
public class Recur
public static void main(String[] argv)
recur();
static void recur()
Object[] o = null;
try
while(true)
Object[] newO = new Object[1];
newO[0] = o;
o = newO;
finally
recur();
C:\JavaTools>java Recur
#
# An unexpected error has been detected by Java Runtime Environment:
#
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6816, tid
=5432
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)
# Problematic frame:
# V [jvm.dll+0x2e5c3d]
#
# An error report file with more information is saved as:
# C:\JavaTools\hs_err_pid6816.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
哒哒!!
(您可以限制对 Unsafe 的访问,但不能限制上述任何一个。)
【讨论】:
这只是Java栈或堆内存用完了,和JVM崩溃不一样。请参阅 Peter Lawrey 对 JVM 崩溃情况的回答。 “崩溃”的定义有些主观。 Unsafe 计划是我没有想到的。但是在内部堆之外运行 JVM 可能会导致“真正的”崩溃。 (请注意,JVM“通常”处理无限递归,只有一个未处理的异常关闭,但它高度依赖于上下文。)【参考方案4】:要让整个计算机崩溃,我会这样做:
public static void crashComputer()
while(true)
Thread thread = new Thread(new Runnable()
@Override
public void run()
while(true)
crashComputer();
);
thread.start();
public static void crashJVM()
while(true)
crashJVM();
crashComputer 函数大约需要 2 秒才能使整个计算机崩溃。您可以通过按住电源按钮来阻止它崩溃。
crashJVM函数通过堆栈重载,只使JVM崩溃,导致堆栈溢出(这就是本网站名称的由来)。
警告:使用风险自负。这不会损坏您的计算机,但如果您忘记单击文档或其他内容上的保存,我不会承担任何责任。
【讨论】:
【参考方案5】:也可以使用 OutOfMemoryError 使应用程序崩溃。
public class StringOutOfMemory
public static void main(String[] args)
int i = 0;
StringBuilder s = new StringBuilder("a");
while (true)
s.append("ahgsdgjsdffsdfhsdgfsdfsdsfhdsgksdgkfgsdkfkdghfksdkfsdkfdkjfskdfkjsdfkdksdkdfjksjkhsdfjkfsdkjfsdhjkfsdjkfhdjkfkjsdfkjdsjkfd");
System.out.println(i++);
输出:
java.lang.OutOfMemoryError
【讨论】:
以上是关于编写Java代码使java虚拟机崩溃的主要内容,如果未能解决你的问题,请参考以下文章