Приводит ли какой-либо фрагмент кода, записанный в блоке catch, к использованию большего количества ресурсов? - PullRequest
1 голос
/ 06 декабря 2011

У меня есть фрагмент кода, и в блоке catch я намеренно добавляю фрагмент кода, так как я уверен, что поток когда-нибудь придет в ловушку. Таким образом, для большого проекта этот тип кодирования приводит к еще большему использованию ресурсов, так как логически, если возникает какое-либо исключение, приводит к созданию нового потока или удержанию в JVM, так что это означает некоторое использование ресурсов, и у меня есть способ избежать возникновения исключения и сделайте кусок кода где-нибудь в нужном месте.

Позвольте уточнить -

char ch = 'c'
try{
Integer.parse(character.toString(ch));
}(Exception e){
//SOME VERY IMPORTANT OPERATION LIKE LOGIC MATHEMATICAL BASED
}

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

char ch = 'c';
if(!Character.isDigit(ch))
 //SOME VERY IMPORTANT OPERATION LIKE LOGIC MATHEMATICAL BASED

Сейчас я не написал ни одного исключения, но оно будет работать правильно.

Теперь мой вопрос: 1-й подход кодирования уловов приведет к некоторому внутреннему использованию ресурсов, I mean does JVM internally leads to some internal resource usage and this kind of catch coding should be avoided as max as possible or I can definately use the 1st approach

Ответы [ 6 ]

4 голосов
/ 06 декабря 2011

Очень сложно понять вопрос, но некоторые общие моменты:

  • Исключения составляют исключительные события.Исключения не должны использоваться для нормальных условий.Создание исключения является дорогостоящей операцией.

  • try/catch/finally блоки не являются дорогостоящими вообще .JVM оптимизированы для их очень эффективной обработки, потому что правильно написанный код использует их повсеместно.

Стоимость приходит, когда возникает исключение , а не когдаВы используете try/catch/finally в своем коде.Поэтому вы можете свободно использовать try/catch/finally повсеместно, но избегайте написания кода, основанного на исключениях в обычном порядке.

Например, вот плохой примерс использованием исключений:

/**
 * Gets a `Thingy` instance based on the given `Foo`.
 *
 * @param   foo     the `Foo`, or `null`
 * @return  the new `Thingy` based on the given `Foo`, or `null` if `foo`
 *          is `null`
 * @throws  ThingyException if no `Thingy` can be constructed for the given `Foo`
 */
Thingy getThingyForFoo(Foo foo) {
throws ThingyException
    ExpensiveThingyFactory factory = getExpensiveThingyFactory();
    try {
        return factory.getThingy(foo);
    }
    catch (NullPointerException npe) {
        return null;
    }
    finally {
        factory.release();
    }
}

Это плохо, потому что метод ясно говорит, что передача аргумента null foo является нормальным вариантом использования, но код полагается на factory.getThingy(foo), бросая NullPointerExceptionкогда вы проходите в foo = null.Поскольку это задокументированный нормальный вариант использования, вы явно его кодируете:

/**
 * Gets a `Thingy` instance based on the given `Foo`.
 *
 * @param   foo     the `Foo`, or `null`
 * @return  the new `Thingy` based on the given `Foo`, or `null` if `foo`
 *          is `null`
 * @throws  ThingyException if no `Thingy` can be constructed for the given `Foo`
 */
Thingy getThingyForFoo(Foo foo) {
throws ThingyException
    ExpensiveThingyFactory factory = null;
    if (foo == null) {
        return null;
    }
    factory = getExpensiveThingyFactory();
    try {
        return factory.getThingy(foo);
    }
    finally {
        factory.release();
    }
}

try/finally в этом не дорогой. Бросок Исключение стоит дорого.

1 голос
/ 06 декабря 2011

Давайте поговорим о том, что дорого об исключениях и обработке исключений.

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

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

  • Действительно дорогостоящая часть обработки исключений в Java - это создание иинициализация объекта исключения до его выброса.И затраты происходят потому, что исключение должно захватывать и записывать информацию, которая позже будет выведена в трассировку стека.И стоимость пропорциональна глубине стека в точке, где создается объект исключения (и, как правило, также выбрасывается).

Суть в том, что общая стоимость создания, бросанияРаспространение исключения обычно составляет тысяч инструкций.Следовательно, Java-пословица о том, что исключения должны использоваться только для исключительных условий.

Так что же это означает на практике?

Давайте рассмотрим пример, аналогичный вашему:

public int toInt(String str, int dflt) {
  try {
    return Integer.parse(str);
  } (NumberFormatException e) {
    return dflt;
  }
}

private static final Pattern numberPattern = Pattern.compile("-?\\d+");
public int toInt(String str, int dflt) {
  if (numberPattern.matcher(str).matches()) {
    return Integer.parse(str);
  } else {
    return dflt;
  }
}

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

Что является более эффективным?Ну, это зависит от вероятности того, что метод вызывается с неправильным номером.Например, если недопустимые номера встречаются один раз в 1000 вызовов, то во второй версии в 999 раз в 1000 раз применяется регулярное выражение без необходимости, чтобы избежать 1 случая, когда выбрасывается исключение;т.е. первая версия в среднем быстрее.С другой стороны, если недопустимые числа встречаются 1 раз в 2, то мы сравниваем стоимость двух вызовов для механизма регулярных выражений с одним созданным, брошенным и перехваченным исключением.И мои деньги на второй версии в среднем значительно быстрее.

В общем, решение, основанное исключительно на производительности, сводится к некоторой простой математике.Если p - это вероятность возникновения исключения, A - это средняя стоимость теста, чтобы избежать исключения, а E - средняя стоимость создания / выброса / вылова, тогда вам нужно сравнить * 1037.* с (1 - p) * A.Если первое меньше, то пусть произойдет исключение, а если второе меньше, избегайте исключения.

Конечно, получить точные значения или оценки для p, A и E сложно,Таким образом, более практичный подход заключается в том, чтобы начать с интуиции, а затем профилировать свое приложение, чтобы увидеть необходимость оптимизации.

1 голос
/ 06 декабря 2011

Я не думаю, что при использовании блока try catch возникает много накладных расходов, но когда возникает исключение, возникает перегрузка стека до тех пор, пока не будет найден соответствующий блок catch.

Если исключение делаетне происходит, нет наказания.

0 голосов
/ 06 декабря 2011

Существуют накладные расходы при использовании блока catch или даже при использовании try / catch. Но накладные расходы связаны с нарушением оптимизации сгенерированного кода и могут составлять несколько десятков дополнительных машинных инструкций (плюс, конечно, стоимость обработки самого исключения).

Но код в блоке catch выполняется в том же потоке, что и основная подпрограмма, и использует тот же кадр автостека, и, кроме внутренних блокировок, используемых во время обработки исключений, дополнительные «ресурсы» не используются - Исключением является только новый объект, при выполнении catch не выполняется никаких блокировок, нет существенных изменений в занимаемой памяти и т. д.

0 голосов
/ 06 декабря 2011

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

Если я понимаю ваш вопрос, похоже, что ваш код полагается на исключения для нормального потока - то есть вы ожидаете регулярно вводить catch блоков.

Это не хороший способ кодирования, и он, безусловно, использует больше ресурсов, чем код, который позволяет избежать создания исключений, которых можно избежать (например, используя методы проверки состояния с if/else вместо того, чтобы полагаться исключительно на try/catch).

Кодирование с использованием try / catch не является неэффективным. Код, который обычно генерирует множество исключений и использует их для нормального потока управления, не эффективен.

0 голосов
/ 06 декабря 2011

Я отвечаю на этот вопрос, предполагая, что базовое использование Java подвергается сомнению.

Нет, код в блоке catch не будет вести себя иначе, чем код, написанный где-либо еще. Если вы создаете «новые» объекты внутри вашего блока catch, тогда будет использоваться больше ресурсов, но это ничем не отличается от «нового» объекта, создаваемого где-либо еще.

JVM не будет создавать объекты, пока они не будут указаны в коде. Поэтому, если ваш catch блок не выполняется, никаких дополнительных ресурсов не требуется.

Блоки

Catch также выполняются в том же потоке, что и блок Try. Вот почему e.printStackTrace() может показать вам, что выполнялось

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...