Java 程序会崩溃吗?
Posted
技术标签:
【中文标题】Java 程序会崩溃吗?【英文标题】:Do Java programs ever crash? 【发布时间】:2011-02-21 06:32:51 【问题描述】:我是一名 c++ 程序员,我对 java 知之甚少。我知道 java 程序员不必像 C++ 那样直接使用内存。我也知道 C++ 应用程序中的大多数崩溃都是由于内存损坏造成的。
那么,用 Java 编写的应用程序会因为内存相关问题而崩溃吗?
谢谢
【问题讨论】:
前几天 Netbeans 撞到我身上并设法用它取出 JVM,所以是的,它们可能会崩溃:p Java programs 在 JVM 中运行可能会崩溃,但之后 JVM 通常会正常关闭。 【参考方案1】:与其他一些答案相反,我声称 Java 程序会像 C++ 程序一样经常崩溃,甚至可能更多。
对于“崩溃”,大多数人理解为程序遇到未正确处理的错误,导致应用程序终止。好吧,这当然会发生,并且与 Java 处理内存的方式无关。
这是一件好的事情。是什么让 C++ 如此危险,而 Java 相对安全,正是因为 Java 会在 C++ 继续运行的情况下崩溃,尽管它会做非常错误和潜在危险的事情(例如写入未初始化的内存、缓冲区溢出……)。 Java 的崩溃(例如抛出异常)可以防止更严重的损害。另一方面,C++ 应用程序(由于错误终止失败)可能会损坏外部数据或系统。或者他们可能只是提供了一个错误(但看似合理)的结果。
Java 防范的是这些危险,而不是本身的崩溃。
【讨论】:
+1 未定义的行为在程序中并不是一件好事。 另一方面,如果您不希望程序继续运行,并且您绝对想为计算中的任何潜在错误抛出异常,则您冒着引爆火箭的风险。查看 Ariane 5 的首次发布。 +1 崩溃比未定义的行为要好。但是,编译错误比两者都好,而且我认为 C++ 具有更好的语义来创建编译时错误。 @Viktor Sehr:哦,我完全同意。【参考方案2】:java 可能会崩溃。
原因可能是..
OutOfMemoryError
***Error
OutOfMemoryError: PermGen space.
OutOfMemoryError 当 Java 虚拟机因为内存不足而无法分配对象时抛出,并且垃圾收集器无法提供更多内存。
***Error ***Exception 抛出执行堆栈溢出错误,通常是在非常深或无限递归的情况下。
OutOfMemoryError:PermGen 空间 详细消息 PermGen space 指示永久代已满。永久代是堆中存储类和方法对象的区域。如果应用程序加载了大量的类,则可能需要使用 -XX:MaxPermSize 选项来增加永久代的大小。
问题是关于可能导致崩溃的内存问题。
其他可能导致崩溃但可以被程序捕获并从 posibilty 中恢复的问题 是任何 runtimeExceptions。 即
算术异常, 数组存储异常, 缓冲区溢出异常, 缓冲区下溢异常, 不能重做异常, 无法撤消异常, ClassCastException,CMMException, 并发修改异常, DOMException,EmptyStackException, IllegalArgumentException, 非法监视器状态异常, 非法路径状态异常, 非法状态异常, 成像操作异常, IndexOutOfBoundsException, 缺少资源异常, 负数组大小异常, NoSuchElementException, 空指针异常, 配置文件数据异常, 提供者异常, 光栅格式异常, 安全异常,系统异常, 未声明的ThrowableException, UnmodifiableSetException, 不支持的操作异常
我不会在这里讨论这些。但看看... link text
【讨论】:
不存在 PermGenSpaceException 之类的东西 即使出现 NullPointerException,您的程序仍然可以运行。 “Java 运行时环境检测到致命错误:SIGSEGV (0xb) at pc=0x8fffa62d, pid=22963, tid=3065453424。”它可能会以相当不友好的方式崩溃。 没有OutOfMemoryException
这样的东西。但是有OutOfMemoryError
。同样没有***Exception
- 但***Error
。准确很重要。
@jeff ,感谢您的详细解释【参考方案3】:
是的,它可以:)
public void test()
test();
这将因***Error
而崩溃。还有一些其他的 - 例如内存不足也会导致崩溃 (OutOfMemoryError
)。
【讨论】:
+1 是的,尽管此堆栈溢出与 C++ 缓冲区溢出非常不同。***Error
,而不是***Exception
。
再次,您可以捕捉到此错误并安全地继续,如果您也选择了,就好像它没有发生一样。【参考方案4】:
C++ 中的内存损坏不只是发生。它们是由软件错误引起的,例如写入数组末尾。这样做也会导致 Java 崩溃。 (没有一种语言会采用包含错误的源代码并生成一个执行您最初想要的程序的程序。)不同之处在于,在 C++ 中,您会得到“未定义的行为”,即程序可能会在其他地方崩溃。当您尝试写入数组末尾时,Java 程序将崩溃,这使得 找到错误变得更加容易。
【讨论】:
【参考方案5】:Java 程序总是崩溃。我遇到的最常见的原因是内存耗尽和未处理的异常。
【讨论】:
【参考方案6】:他们当然会崩溃:)
除了所有很好的答案之外,还有简单明了的 JVM 崩溃。例如,这是我问的一个问题,涉及一个损坏的 JVM 案例,我可以使用特定的数据集可靠地崩溃(这不是我的错:这个“不应该”发生......但它有;)
我在一些奇怪的情况下看到服务器端 JVM 崩溃(过去 Tomcat+Hibernate+Sun VM 问题,过去通过更改 Tomcat 或 Sun VM 得到了修复)。
我已经看到桌面端的 JVM 在它们不应该崩溃的时候崩溃(将商业 Java 软件运送到许多桌面机器往往会增加你目睹这种事情的可能性)。
我见过的最好的是一个 JVM 完全损坏,我可以在几台机器上可靠地崩溃,而且,不,这些机器并不是都有问题,它们是坚如磐石的工作站(因为那个帖子,我在几台机器上都试过了,都可以重现):
Java VM: reproducable SIGSEGV on both 1.6.0_17 and 1.6.0_18, how to report?
(请注意,有很多其他 JVM 在同一台机器上运行良好,具有相同的软件/数据集)。
目睹 JVM 崩溃时,我做的第一件事是更改软件组件:通常将 JVM 升级到最新版本。
【讨论】:
我必须提一下,我绝不是在暗示 Java 不稳定:我的生产服务器的正常运行时间为两年(经过强化的 Debian Linux 系统往往不需要很多“关键”要求重启的补丁 ;) 上面运行着几乎不需要重启的 Java 服务器(它们已重启,但不是因为崩溃和/或内存相关问题)。【参考方案7】:因此,用 Java 编写的应用程序将 永远不会因为内存相关而崩溃 问题。
OutOfMemoryError
肯定是与内存相关的问题。此外,当遇到 JVM 中的错误(通常用 C 或 C++ 编写)或出现硬件问题(例如 RAM 损坏)时,您可能会遇到“真正的”崩溃(segfault)。当您在未验证它的 JVM(例如嵌入式系统的 JVM)上运行无效字节码时,也可能出现这种情况。
但通常,是的,Java 程序不会出现段错误。
【讨论】:
【参考方案8】:没有。 Java 应用程序可能由于内存问题而崩溃。虽然 Java 确实有内置的内存管理,但它绝不是完美的。只是为你做了很多辛苦的工作。
正如在其他一些答案中提到的,Java 确实有一个相当特殊的内存分配系统,它确实涉及相当多的手动管理,如果你不小心并且没有,实际上很容易耗尽这个分配它为您的应用程序正确设置。
(参见 Java 的 -Xmx 和 -Xms 参数)
【讨论】:
【参考方案9】:虽然 JVM 本身不太可能崩溃,但您的程序完全有可能因与内存相关的问题而崩溃,例如由于永远不会超出范围的对象导致内存泄漏。
(edit: JVM 是一个高度优化的平台,虽然 bug 很少见,但它们仍然偶尔会出现,当然,正如其他人在这里提到的,如果你有硬件问题,例如损坏的 I/O 或 RAM,JVM 会死掉)
【讨论】:
【参考方案10】:此程序将抛出OutOfMemoryException
并崩溃。
void crash(List list)
while (true)
list.add(new Object());
【讨论】:
OutOfMemoryError
,不是OutOfMemoryException
。
您可以捕获 OutOfMemoryError,并清除列表并继续运行,就好像它从未发生过一样。因此,即使是可能导致程序崩溃的东西也可以在 Java 中恢复。【参考方案11】:
严重的崩溃看起来像这样:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00000000, pid=3387, tid=166603048020
#
# JRE version: 6.0_14-b08
# Java VM: Java HotSpot(TM) Server VM (14.0-b16 mixed mode linux-x86 )
# Problematic frame:
# C 0x00000000
#
# An error report file with more information is saved as:
# .....hs_err_pid3387.log
造成这种情况的不是 java 程序,而是 vm 本身的代码。几年来非常罕见。
【讨论】:
【参考方案12】:如果你想测试如果 JVM 真的崩溃了会发生什么,试试这个函数(我用它来测试我的崩溃处理程序 :)。不适用于安全环境或非 Sun JDK。
/**
* Crashes the JVM, by copying 1 byte from address 1 to address 1. If this did
* not crash the machine already, we copy a byte from -1 to -1 :). Never call
* this except for debugging problems related to handling system crashes.
*/
public static void crash()
Unsafe unsafe;
try
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
catch (Exception ex)
throw new RuntimeException("Can't get Unsafe instance to crash app.", ex);
log.fatal("Here we are and say good bye, the app ist now about to die...");
// Crash now!
unsafe.copyMemory(1,1,1);
// Still alive? Than the following line will help... Crash now!
unsafe.copyMemory(-1,-1,1);
【讨论】:
以上是关于Java 程序会崩溃吗?的主要内容,如果未能解决你的问题,请参考以下文章
Crashlytics/Fabric - 删除帐户/项目后我的应用程序会崩溃吗?