2014-10-02 4 views
0

Есть ли какие-либо инструкции JVM, которые гарантированно не будут бросать?Какие инструкции JVM нельзя выбрасывать?

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

int foo() { 
    try { return 1; } 
    catch (Throwable t) { return 2; } 
} 

int bar() { return 1; } 

Существуют ли какие-либо случаи (за исключением, если блок попробовать пуст), где поведение гарантированно остаются теми же после удаления Try-фиксатор ?

+0

Возможный дубликат [No-throw VirtualMachineError гарантирует] (http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror-guarantees) – Raedwald

ответ

1

Вы задаете неправильный вопрос. Если вы ожидаете выбросить VirtualMachineError, вы не можете ожидать, что поведение будет гарантировано оставаться неизменным, независимо от того, есть ли try … catch или нет.

Чтобы остаться в вашем примере:

try { return 1; } 
catch (Throwable t) { return 2; } 

Для этого кода, будет обработчик исключений для двух команд байт кода iload_1, ireturn. Это означает, что если VirtualMachineError поднят непосредственно перед инструкцией iload_1 или сразу после того, как JVM столкнулась с инструкцией ireturn, ошибка не будет обнаружена. И никто не может отличить эту ситуацию от ситуации, когда обработчик исключений удален, и ошибка возникает между этими инструкциями.

Сравнить с The Java® Virtual Machine Specification, Java SE 8 Edition §2.10. Exceptions:

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

Так что для случая VirtualMachineError, отсутствие обработчика исключений не будет никакой разницы, никто не может заметить и JVM может отложить ошибка в любом случае в зависимости от внутреннего состояния оптимизации кода. В другом случае возможна ireturn сбрасывание IllegalMonitorStateException.

В конце концов, вопрос в том, что вы собираетесь оптимизировать. Обработчики исключений обычно не влияют на производительность, поскольку JVM не затрагивает их, если исключение не должно обрабатываться.

+0

Спасибо за ответ, Хольгер, очень полезно! Чтение главы «2.10. Исключения», похоже, не все «VirtualMachineError» являются асинхронными. В частности, генерируется синхронное исключение при выполнении команды «Вызывает ограничение на ресурс, который должен быть превышен, например, когда используется слишком много памяти».Таким образом, кажется, что почти любая команда может вызвать такое исключение - или как вы можете быть уверены, что 'iload' никогда не вызывает« OutOfMemoryError »? –

+0

'iload' обрабатывает текущий, предварительно выделенный стек стека. Фрейм стека выделяется при вызове метода, и задача верификатора состоит в том, чтобы гарантировать, что никакая команда не может превышать размер объявленного размера стека. Таким образом, 'iload' не может вызывать' OutOfMemoryError'. См. [§ 2.6. Frames] (http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6) – Holger

+0

Спасибо за понимание, действительно полезно! –

0

Теоретически все может вызывать исключение. Но такие исключения не поддаются лечению в любом случае, вы также можете исключить исключение своего приложения.

+1

Спасибо. Я спрашиваю больше как автора компилятора: безопасно ли исключить такой обработчик? Я думаю, что ответ отрицательный. –

+1

@Lukas Ну, поведение ошибок виртуальной машины и асинхронных исключений, очевидно, зависит от реализации, поэтому я бы не стал беспокоиться об этом. Идите вперед и делайте оптимизацию, если хотите (до тех пор, пока вас не интересует отладка) – Antimony

Смежные вопросы