需要解释为什么会发生EXCEPTION_ACCESS_VIOLATION

时间:2011-02-04 09:39:38

标签: memory-management jvm segmentation-fault access-violation

嗨,我知道我要展示的这个错误无法通过代码修复。我只是想知道为什么以及它是如何引起的,我也知道它是由于JVM试图访问另一个程序的地址空间。

 A fatal error has been detected by the Java Runtime Environment:

  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6dcd422a, pid=4024, tid=3900

 JRE version: 6.0_14-b08
 Java VM: Java HotSpot(TM) Server VM (14.0-b16 mixed mode windows-x86 )
 Problematic frame:
 V  [jvm.dll+0x17422a]

An error report file with more information is saved as:
C:\PServer\server\bin\hs_err_pid4024.log

If you would like to submit a bug report, please visit:
http://java.sun.com/webapps/bugreport/crash.jsp

1 个答案:

答案 0 :(得分:1)

Tanenbaum的“现代操作系统”一书,可在线获取:

http://lovingod.host.sk/tanenbaum/Unix-Linux-Windows.html

深入探讨这个话题。 (第4章是内存管理,第4.8章是内存分段)。简短版本:

如果您PC上的多个程序可以访问彼此的内存,那将是非常糟糕的。实际上即使在一个程序中,即使在一个线程中,您也有多个内存区域,这些区域不能相互影响。通常一个进程至少有一个称为“堆栈”的内存区域和一个称为“堆”的区域(通常每个进程每个线程有一个堆+一个堆栈。可能有更多的段,但这是依赖于实现的,它不是这里解释的问题)。在堆栈上,诸如函数的参数和保存的局部变量之类的东西。在堆上是保存的变量,编译时编译器无法确定大小和生命周期(在Java中,您使用“new”-Operator的所有内容都是如此。例如:

public void bar(String hi, int myInt)
{
  String foo = new String("foobar");
}
在这个例子中,

是两个String对象:(由“foo”和“hi”引用)。这两个对象都在堆上(你知道这一点,因为在某些时候两个字符串都是使用“new”分配的。在这个例子中,3个值在堆栈上。这将是“myInt”,“hi”和“foo”。重要的是要意识到“hi”和“foo”并不直接包含Strings,而是它们包含一些id,告诉他们在堆上他们可以找到String。(这并不容易使用java来解释因为java抽象很多。在C“hi”和“foo”中将是一个指针,它实际上只是一个整数,表示存储实际值的堆中的地址。)

你可能会问自己为什么还有堆栈和堆。为什么不把所有东西放在同一个地方。不幸的是,解释超出了这个答案的范围。阅读我链接的书;-)。简短的版本是堆栈和堆被不同地管理,并且出于优化的原因进行分离。

堆栈和堆的大小是有限的。 (在Linux上执行ulimit -a,你会得到一个包含“数据段大小”(堆)和“堆栈大小”的列表(是啊......堆栈: - ))。)。

堆栈只会增长。就像一个数组越来越大,如果你追加越来越多的数据。最终你的空间不足了。在这种情况下,您可能最终写入不属于您的内存区域。那将是非常糟糕的。因此,如果发生这种情况,操作系统会注意到并停止程序。在Linux上,您会收到“Segmenation fault”,在Windows上会出现“访问冲突”。

在C等其他语言中,您需要手动管理内存。一个微小的错误很容易导致你不小心写入一些不属于你的空间。在Java中,您有“自动内存管理”,这意味着JVM会为您完成所有这些操作。你不需要关心,并且作为开发人员从你的肩膀上承担负担(通常是这样。我打赌那里的人会对“负载”部分不同意;-))。这意味着它/应该/不可能用java产生分段错误。不幸的是,JVM并不完美。有时候它有bug和搞砸了。然后你得到你得到的东西。