2012-01-04 1 views
12

Я пришел на Java из C++. В мире C++ мы обращаем внимание на безопасность исключений и отмечаем, что мутаторы могут предоставлять разные гарантии перед исключениями, которые выдает сам мутатор или метод, которым он делегирует (минимальный, сильный, не-бросок). Реализация метода, который имеет сильную гарантию исключения, требует, чтобы некоторые основные операции гарантировали никогда не выдавать исключение. JLS делает утверждения о том, какие операции могут выполнять какие-либо исключения, но ошибка VirtualMachineError представляет проблему. Каркнул JLS:No-throw VirtualMachineError гарантирует

внутренняя ошибка или ресурс ограничение предотвращает виртуальную машину Java от реализации семантики Java-программирования языка; в этом случае бросается экземпляр подкласса VirtualMachineError.

JLS говорит не более о VirtualMachineError. «Внутренняя ошибка» означает ошибку в JVM, поэтому меня это не интересует: перед ошибками в JVM все ставки отключены. Но как насчет «ограничения ресурсов»? Есть ли какие-либо операции, которые гарантированы, никогда не сбой из-за ограничения ресурсов?

+0

Ближе всего к ответу будет 'try {...} catch (Throwable t) {}'. Конечно, если память исчерпана, любое продолжение окажется почти невозможным. Теперь это не отличается в C++. –

+2

Я отвечаю на свой вопрос. Часто задаваемые вопросы даже поощряют это. – Raedwald

ответ

12

Java Virtual Machine Specification Каркнул:

Данная спецификация не может предсказать, где внутренние ошибки или ресурс ограничения могут возникнуть и не санкционировать именно тогда, когда они могут быть представлены. Таким образом, любой из VirtualMachineError подклассов , определенных ниже, может быть выброшен в любой момент во время работы виртуальной машины Java:

В Java поэтому без исключения гарантии не может быть сделана в отношении VirtualMachineError исключений. Все гарантии исключений должны подлежать квалификации «... но не если выбрано VirtualMachineError». Это один из способов, с помощью которых Java отличается от C++.

Это также говорит о том, что исключить исключение VirtualMachineError не так много, потому что программа находится в неопределенном состоянии, если она была выбрана. К сожалению, это относится к исключениям OutOfMemoryError. Несчастливо, потому что если одна из нескольких задач терпит неудачу, потому что для этого требуется слишком много памяти, мы могли бы продолжить другие задачи.

+0

Вы отвечаете на свой вопрос или просто добавляете к нему? – skaffman

+1

Я отвечаю на свой вопрос. – Raedwald

+0

Ошибки VirtualMachineError и OutOfMemoryError являются ошибками. Вместо того, чтобы просто сбой, Java выдает ошибку в некоторых ненормальных условиях. Тем не менее, ни один из подклассов Error не предназначен для большинства программ. Ошибки можно отличить от Исключений, которые могут быть пойманы. Исключительные гарантии, продвигаемые Herb Sutter, могут быть применены и к Java, для нормальных Исключений. –

1

Если это ограничение ресурсов, на первом месте, никаких операций не происходит. Вот ссылка для отличного примера, чтобы иметь VirtualMachineError. Virtual machine error

Эта ошибка не является чем-то вроде OutofMemoryError, где к этому моменту могут выполняться некоторые операции.

+0

" никаких операций не происходит ». Это будет «сильная гарантия за исключением». Но такой гарантии не делается. – Raedwald

+0

Если моя интерпретация верна, на основе вышеприведенного примера, прежде чем начать работу с VM, она проверяет определенные ресурсы, такие как -Xmx, и не может найти определенный размер памяти и ошибку выброса. Я согласен с вашей точкой зрения на отсутствие гарантии, но не знаю почему. – kosa

1

Я вижу, что вы ответили на свой собственный вопрос, и я могу понять, почему это было бы мягко удивительно для вас, исходя из строгого фона C++. Это просто реальность управляемой памяти (виртуальных) машин, и это не ограничивается только java. Память может закончиться, поскольку JVM ограничена тем, сколько кучи она может использовать (настраивается в командной строке java).

В некоторой степени аналогичный, но не эквивалентный в мире C++/машинного кода будет GENERAL_PROTECTION_FAULT (или SEGMENTATION_FAULT, если вы на * NIX), который вы получите при попытке адресовать память, которая не была выделена, или вне вашего виртуального адресного пространства.Предоставление «надежной гарантии исключения» перед лицом этого сценария также сложно, поскольку причиной может быть либо ошибка в коде, либо полностью вне контроля программы.

+0

SEGV указывает на ошибку в программе. Его аналогия в Java - это «NullPointerException». – Raedwald

+0

Я не вижу, как это общая функция управляемой виртуальной машины. JVMS позволяет вызывать «OutOfMemoryError», даже если вы не используете 'new' или пытаетесь загрузить класс. – Raedwald

+0

@ Raedwald вы получите только NPE при попытке ссылаться на «null». Вы получите OutOfMemoryError только после того, как вы попытаетесь выделить больше памяти (или вы вызовете метод, который делает), и GC выполнил, и недостаточно памяти освободится. –

0

В Java вы можете вызвать Thread.stop() или остановить (Throwable) в любое время. Большинство ошибок считаются настолько критичными, что вы не должны пытаться их обрабатывать, если не знаете, что делаете.

После разработки Java-приложения на стороне сервера в течение 12 лет я могу сказать, что я никогда не слышал, чтобы кто-то беспокоился о случайных исключениях. Я подозреваю, что это просто не проблема, о которой вам нужно беспокоиться в Java.

Можете ли вы привести пример того, почему вы считаете, что вам нужна гарантия, поскольку, вероятно, будет другой способ решить проблему?

+2

Исключение 'OutOfMemoryError' - самый интересный случай. Как я уже сказал в своем собственном ответе: «Несчастливо, потому что если одна из нескольких задач терпит неудачу, потому что для этого требуется слишком много памяти, мы могли бы продолжить другие задачи. Но если JVM может вызывать 'OutOfMemoryError', мы не можем полагаться на то, что наша программа находится в правильном состоянии, когда мы поймаем' OutOfMemoryError'. Это делает ненадежным подход к отказу от попыток. – Raedwald

+0

Добавлен недостающий «NOT» перед тем, как «попытаться справиться с ними». –

+2

@ Raedwald Вы правы, что отказ от OOME является ненадежным.Что вам нужно сделать, так это определить максимальную память, в которой вы ожидаете, что весь JVM завершится с ошибкой (а не только мягкий предел) и не будет выполнять операции, которые могут потерпеть неудачу, потому что вы не знаете, сколько памяти они используют. В худшем случае вам нужно использовать отдельный процесс, который можно убить повторно, по мере необходимости. (Это также защищает от ошибок в библиотеках JNI) –