Мы знаем, что ловить исключения дорого. Но стоит ли также использовать блок try-catch в Java, даже если исключение не выдается?
Я нашел вопрос / ответ о переполнении стека. Почему стоит попробовать блоки? , но это для .NET .
java
performance
try-catch
jsedano
источник
источник
try { /* do stuff */ } finally { /* make sure to release resources */ }
законно и полезноfinally
блока, используяtry-with-resources
Ответы:
try
почти не имеет расходов вообще. Вместо того, чтобы выполнять настройкуtry
во время выполнения, метаданные кода структурированы во время компиляции, так что, когда выдается исключение, он теперь выполняет относительно дорогую операцию обхода стека и проверки, существуют ли какие-либоtry
блоки, которые бы перехватили это. исключение. С точки зрения непрофессионала, он такжеtry
может быть бесплатным. На самом деле это исключение, которое стоит вам - но если вы не выбросите сотни или тысячи исключений, вы все равно не заметите цену.try
имеет некоторые незначительные расходы, связанные с этим. Java не может оптимизировать код вtry
блоке, как в противном случае. Например, Java часто будет переставлять инструкции в методе, чтобы он работал быстрее, но Java также должна гарантировать, что, если выдается исключение, выполнение метода наблюдается так, как если бы его операторы, как написано в исходном коде, выполнялись по порядку до какой-то строки.Потому что в
try
блоке может быть сгенерировано исключение (в любой строке блока try! Некоторые исключения генерируются асинхронно, например, путем вызоваstop
потока (что устарело), и даже, кроме того, что OutOfMemoryError может произойти почти где угодно), и все же это может быть перехвачен, и код продолжит выполнение впоследствии в том же методе, более трудно рассуждать об оптимизации, которая может быть сделана, поэтому они менее вероятны. (Кто-то должен был бы запрограммировать компилятор, чтобы он делал это, рассуждал и гарантировал правильность и т. Д. Это было бы большой болью для чего-то, что должно было быть «исключительным») Но опять же, на практике вы не заметите таких вещей.источник
try...finally
блокирует ли блокcatch
также некоторые оптимизации?Exception
объекта - это то, что занимает большую часть времени.Давайте измерим это, не так ли?
На моем компьютере это печатает что-то вроде:
По крайней мере, в этом тривиальном примере оператор try не оказал заметного влияния на производительность. Не стесняйтесь измерять более сложные.
Вообще говоря, я рекомендую не беспокоиться о стоимости производительности языковых конструкций, пока в вашем коде не появится фактическая проблема производительности. Или , как Дональд Кнут поставил его: «преждевременная оптимизация есть корень всех зол».
источник
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
и цикл, и его дополнение присутствуют в сгенерированном собственном коде. И нет, абстрактные методы не являются встроенными, потому что их вызывающая сторона не только вовремя компилируется (предположительно, потому что она не вызывается достаточно раз).try
/catch
может оказать некоторое влияние на производительность. Это потому, что это мешает JVM выполнять некоторые оптимизации. Джошуа Блох в «Эффективной Яве» сказал следующее:источник
Да, как говорили другие,
try
блок запрещает некоторые оптимизации для{}
окружающих его персонажей. В частности, оптимизатор должен предполагать, что исключение может произойти в любой точке блока, поэтому нет гарантии, что операторы будут выполнены.Например:
Без этого
try
значение, рассчитанное для присваивания,x
может быть сохранено как «общее подвыражение» и использовано для присвоенияy
. Но из-заtry
отсутствия уверенности в том, что первое выражение когда-либо оценивалось, поэтому выражение необходимо пересчитать. Обычно это не имеет большого значения в «прямолинейном» коде, но может иметь большое значение в цикле.Следует отметить, однако, что это относится ТОЛЬКО к JITCed-коду. javac выполняет лишь незначительную оптимизацию, и интерпретатору байт-кода не требуется никаких затрат для входа / выхода из
try
блока. (Нет байт-кодов, сгенерированных, чтобы отметить границы блока.)И для бестссс:
Вывод:
вывод javap:
Нет "GOTO".
источник
catch/finally
кадр.finally
в байткод, этоtry/catch(Throwable any){...; throw any;}
и это действительно есть улов о ж / фрейме и Throwable , которые должны быть определены (не нулевой) и так далее. Почему вы пытаетесь спорить о теме, вы можете проверить хотя бы какой-нибудь байт-код? Действующее руководство для импл. Наконец, копирование блоков и избегание раздела goto (предыдущий импл), но байт-коды должны быть скопированы в зависимости от того, сколько точек выхода есть.Чтобы понять, почему оптимизация не может быть выполнена, полезно понять основные механизмы. Самый краткий пример, который я смог найти, был реализован в макросах C по адресу: http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html.
Компиляторам часто трудно определить, можно ли локализовать переход на X, Y и Z, поэтому они пропускают оптимизации, которые не могут гарантировать безопасность, но сама реализация довольно легка.
источник
Еще один микробенчмарк ( источник ).
Я создал тест, в котором я измеряю версию кода try-catch и no-try-catch на основе процента исключений. 10% процент означает, что 10% тестовых случаев имели деление на ноль. В одной ситуации он обрабатывается блоком try-catch, в другой - условным оператором. Вот моя таблица результатов:
Что говорит о том, что между этими случаями нет существенной разницы.
источник
Я нашел ловлю NullPointException довольно дорого. Для операций 1.2k время составляло 200 мс и 12 мс, когда я обрабатывал его таким же образом,
if(object==null)
что было довольно хорошим для меня.источник