Нужно объяснить, почему происходит EXCEPTION_ACCESS_VIOLATION - PullRequest
2 голосов
/ 04 февраля 2011

Привет, я знаю, что эту ошибку, которую я собираюсь показать, нельзя исправить с помощью кода.Я просто хочу знать, почему и как это вызвано, и я также знаю, что это связано с тем, что 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 Ответ

1 голос
/ 05 февраля 2011

Книга "Современные операционные системы" от Tanenbaum, которая доступна онлайн здесь:

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

Охватывает тему в глубину. (Глава 4 посвящена управлению памятью, а глава 4.8 - сегментации памяти). Краткая версия:

Было бы очень плохо, если бы несколько программ на вашем ПК могли обращаться к памяти друг друга. На самом деле, даже в одной программе, даже в одном потоке у вас есть несколько областей памяти, которые не должны влиять друг на друга. Обычно процесс имеет как минимум одну область памяти, называемую «стеком», и одну область, называемую «кучей» (обычно каждый процесс имеет одну кучу + один стек на поток. МОЖЕТ быть больше сегментов, но это зависит от реализации, и это не вопрос для объяснения здесь). В стеке сохраняются такие вещи, как аргументы вашей функции и ваши локальные переменные. В куче сохраняются переменные, размер и время жизни которых не может быть определено компилятором во время компиляции (это будет в Java все, что вы используете для оператора "new". Пример:

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

в этом примере два объекта String: (на которые ссылаются "foo" и "hi"). Оба эти объекта находятся в куче (вы знаете это, потому что в какой-то момент обе строки были выделены с использованием «new». И в этом примере 3 значения находятся в стеке. Это будет значение «myInt», «hi» и "foo". Важно понимать, что "hi" и "foo" на самом деле не содержат строк напрямую, но вместо этого они содержат некоторый идентификатор, который говорит им, что они находятся в куче, где они могут найти строку. (Это не так просто чтобы объяснить использование java, потому что java много абстрагирует. В C "hi" и "foo" будет указателем, который на самом деле является просто целым числом, представляющим адрес в куче, где хранится фактическое значение).

Вы можете спросить себя, почему в любом случае есть стек и куча. Почему бы не поставить все на то же место. Объясняя, что, к сожалению, выходит за рамки этого ответа. Прочитайте книгу, которую я связал ;-). Короткая версия состоит в том, что стек и куча управляются по-разному, и разделение выполняется по причинам оптимизации.

Размер стека и кучи ограничен. (В Linux выполните ulimit -a, и вы получите список, включающий «размер сегмента данных» (куча) и «размер стека» (ага ... stack: -)).).

Стек - это то, что только растет. Как массив, который становится все больше и больше, если вы добавляете все больше и больше данных. В конце концов вам не хватает места. В этом случае вы можете закончить запись в той области памяти, которая вам больше не принадлежит. И это было бы очень плохо. Таким образом, операционная система замечает это и останавливает программу, если это произойдет. В Linux вы получаете «Ошибка сегментации», а в Windows - «Нарушение прав доступа».

На других языках, таких как C, вам нужно управлять памятью вручную. Маленькая ошибка может легко заставить вас случайно записать в какое-то пространство, которое вам не принадлежит. В Java у вас есть «автоматическое управление памятью», что означает, что JVM делает все это за вас. Вам не нужно заботиться, и это берет на себя нагрузку как разработчик (обычно так и есть. Могу поспорить, что есть люди, которые не согласятся с «нагрузкой» ;-)). Это означает, что / j / невозможно / невозможно создавать ошибки сегментации с помощью Java. К сожалению, JVM не идеальна. Иногда в нем есть ошибки и ошибки. И тогда вы получите то, что получили.

...