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並不完美。有時它會有錯誤和螺絲。然後你得到你所得到的。