1

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

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 
+3

这看起来像JVM中的错误!你应该填写一个错误报告。 :-)这可能是由内存损坏或指针读取错误导致的,而不是尝试读取另一个程序的内存。 – templatetypedef 2011-02-04 09:40:19

+0

你想了解一般的访问违规背景吗?内存分割等?或者你只是想知道这是由错误引起的? – yankee 2011-02-04 09:41:44

回答

1

从的Tanenbaum的著作 “现代操作系统”,这是可以在这里在线:

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

涵盖深入的话题。 (第4章介绍内存管理,第4.8章介绍内存分段)。短版本:

如果您的PC上的多个程序可以访问彼此的内存将是非常糟糕的。实际上,即使在一个程序中,即使在一个线程中,您也有多个不能相互影响的内存区域。通常一个进程至少有一个称为“堆栈”的内存区域和一个称为“堆”的区域(通常每个进程都有一个堆+每个线程一个堆栈,可能会有更多的段,但这是依赖于实现的,而不是这里的解释很重要)。在堆栈中,像函数的参数和局部变量被保存。在堆中变量保存的是大小和寿命不能在编译时编译器来决定(这将是在您使用“新” - 运算符Java的一切,例如:

public void bar(String hi, int myInt) 
{ 
    String foo = new String("foobar"); 
} 

在这个例子中是两个字符串对象:(由“foo”和“hi”引用),这两个对象都在堆上(你知道这一点,因为在某些时候两个字符串都是使用“new”分配的。这将是“myInt”,“hi”和“foo”的值,认识到“hi”和“foo”并不直接包含字符串,而是包含一些能够告诉它们的id (这很难用java解释,因为java抽象了很多,在C中“hi”和“foo”是一个指针,它实际上是一个指针t表示存储实际值的堆中的地址的整数)。

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

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

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

在其他语言如C中,您需要手动管理您的内存。一个微小的错误很容易导致你意外地写入一些不属于你的空间。在Java中,你有“自动内存管理”,这意味着JVM为你完成所有这些。你不需要关心,而且这会让开发者承担起你的肩上的负担(通常情况是这样,我敢打赌有人会对“负载”部分持不同意见;-))。这意味着它/应该/不可能用java来产生分段错误。不幸的是,JVM并不完美。有时它会有错误和螺丝。然后你得到你所得到的。