Можно ли построить фрагмент кода в Java , который сделал бы гипотетическую java.lang.ChuckNorrisException
неуловимую?
Мысли, которые пришли в голову, используют, например, перехватчики или аспектно-ориентированное программирование .
java
exception
exception-handling
aop
Макс Чарас
источник
источник
finalize()
?Ответы:
Я не пробовал этого, поэтому я не знаю, будет ли JVM ограничивать что-то подобное, но, возможно, вы могли бы скомпилировать код, который генерирует
ChuckNorrisException
, но во время выполнения предоставьте определение класса,ChuckNorrisException
которое не расширяет Throwable .ОБНОВИТЬ:
Не работает Это генерирует ошибку верификатора:
ОБНОВЛЕНИЕ 2:
На самом деле, вы можете заставить это работать, если отключите проверку байтового кода! (
-Xverify:none
)ОБНОВЛЕНИЕ 3:
Для тех, кто следует из дома, вот полный сценарий:
Создайте следующие классы:
Компилировать классы:
Запустить:
Закомментируйте "extends RuntimeException" и перекомпилируйте
ChuckNorrisException.java
только :Запустить:
Запустить без проверки:
источник
Object
вместоThrowable
, тогда? (Компилятор не допустит этого, но, поскольку мы уже отключили верификатор, возможно, для этого можно взломать байт-код.)Обдумав это, я успешно создал неуловимое исключение. Однако я решил назвать его
JulesWinnfield
, а не Чака, потому что это одно исключение из грибовидных облаков. Кроме того, это может быть не совсем то, что вы имели в виду, но это, безусловно, не может быть пойман. Заметим:И вуаля! Неисследованное исключение.
Вывод:
Когда у меня будет немного больше времени, я посмотрю, не смогу ли я придумать что-то еще.
Также проверьте это:
Вызывает переполнение стека - опять же, исключения остаются необработанными.
источник
JulesWinfield
? Разве система не остановится до того, как ее бросят?throw new Whatever()
на самом деле состоит из двух частей:Whatever it = new Whatever(); throw it;
и система умирает до того, как достигнет второй части.class cn extends exception{private cn(){}}
С таким исключением, очевидно, будет обязательно использовать конструктор
System.exit(Integer.MIN_VALUE);
from, потому что это то, что произойдет, если вы бросите такое исключение;)источник
while(true){}
вместоSystem.exit()
.System.exit()
работе, установив менеджер безопасности, который запрещает это. это превратит конструктор в другое исключение (SecurityException), которое может быть перехвачено.Любой код может поймать Throwable. Так что нет, какое бы исключение вы ни создавали, оно будет подклассом Throwable и может быть поймано.
источник
hang
сам в попытке поймать ChuckNorrisException: P(Конечно, технически это исключение никогда не генерируется, но правильное
ChuckNorrisException
не может быть выброшено - оно выбрасывает вас первым.)источник
Любое исключение, которое вы выбрасываете, должно расширять Throwable, чтобы его всегда можно было поймать. Так что ответ - нет.
Если вы хотите , чтобы сделать его трудно обрабатывать, вы можете переопределить методы
getCause(), getMessage()
,getStackTrace()
,toString()
чтобы бросить другиеjava.lang.ChuckNorrisException
.источник
catch(Throwable t)
сохраняет только в переменную, поэтому мои предложения применяются только в следующем блоке, когда пользователь хочет справиться с исключениемМой ответ основан на идее @ jtahlborn, но это полностью работающая Java- программа, которую можно упаковать в файл JAR и даже развернуть на вашем любимом сервере приложений как часть веб-приложения. .
Прежде всего, давайте определим
ChuckNorrisException
класс так, чтобы он не приводил к краху JVM с самого начала (Чак действительно любит разбивать JVM, кстати)Теперь идет
Expendables
класс, чтобы построить это:И, наконец,
Main
класс, чтобы пнуть задницу:Скомпилируйте и запустите его с помощью следующей команды:
Вы получите следующий вывод:
Не удивительно, ведь это удар с разворота :)
источник
В конструкторе вы можете запустить поток, который несколько раз вызывает
originalThread.stop (ChuckNorisException.this)
Поток мог бы перехватить исключение несколько раз, но продолжал бы выбрасывать его, пока он не умрет.
источник
Нет. Все исключения в Java должны быть подклассами
java.lang.Throwable
, и, хотя это может не быть хорошей практикой, вы можете перехватить каждый тип исключения следующим образом:Увидеть java.lang.Throwable Документацию для получения дополнительной информации.
Если вы пытаетесь избежать проверенных исключений (тех, которые должны быть явно обработаны), тогда вы захотите создать подкласс Error или RuntimeException.
источник
На самом деле принятый ответ не так хорош, потому что Java нужно запускать без проверки, то есть код не будет работать в нормальных условиях.
AspectJ на помощь для реального решения !
Исключительный класс:
аспект:
Пример приложения:
Вывод:
источник
Вариант на тему - удивительный факт, что вы можете бросить необъявленные проверенные исключения из кода Java. Поскольку оно не объявлено в сигнатуре методов, компилятор не позволит вам перехватить само исключение, хотя вы можете перехватить его как java.lang.Exception.
Вот вспомогательный класс, который позволяет вам бросать что-либо, объявленное или нет:
Теперь
throw SneakyThrow.sneak(new ChuckNorrisException());
выдает ChuckNorrisException, но компилятор жалуетсяо перехвате исключения, которое не выдается, если ChuckNorrisException является проверенным исключением.
источник
Единственные
ChuckNorrisException
s в Java должны бытьOutOfMemoryError
иStackOverflowError
.Вы действительно можете «поймать» их в том смысле, что
catch(OutOfMemoryError ex)
будет выполняться в случае исключения, но этот блок автоматически сбросит исключение для вызывающей стороны.Я не думаю, что
public class ChuckNorrisError extends Error
это поможет, но вы могли бы попробовать. Я не нашел документации о расширенииError
источник
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Да, и вот ответ: спроектируйте так
java.lang.ChuckNorrisException
, чтобы это не было примеромjava.lang.Throwable
. Почему? Невыбираемый объект по определению неуловим, потому что вы никогда не сможете поймать то, что никогда не бросите.источник
java.lang.ChuckNorrisException
должны быть исключением, не говоря уже о бросаемомВы можете оставить Чака Норриса внутренним или частным и заключить его в капсулу или проглотить его ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
источник
Две фундаментальные проблемы с обработкой исключений в Java заключаются в том, что в ней используется тип исключения, чтобы указать, следует ли предпринимать действия на его основе, и что предполагается, что все, что предпринимает действие на основе исключения (то есть «ловит» его), разрешает основное условие. Было бы полезно иметь средство, с помощью которого объект исключения мог бы решить, какие обработчики должны выполняться, и выполнили ли обработчики, которые выполнялись до сих пор, достаточно вещей, чтобы существующий метод удовлетворял условиям его выхода. Хотя это может быть использовано для создания «неуловимых» исключений, два более масштабных применения будут заключаться в том, чтобы (1) создавать исключения, которые будут рассматриваться как обработанные, только когда они обнаружены кодом, который фактически знает, как с ними работать,
finally
FooException
finally
блока при разматывании aBarException
оба исключения должны распространяться вверх по стеку вызовов; оба должны быть подловлены, но раскручивание должно продолжаться до тех пор, пока оба не будут пойманы). К сожалению, я не думаю, что был бы какой-то способ заставить существующий код обработки исключений работать таким образом, не ломая вещи.источник
finally
очистки блока от более раннего исключения, вполне возможно, что любое исключение, в отсутствие другого, может быть чем-то, что код будет обрабатывать и продолжать, но что обращаться с одним и игнорировать другое было бы плохо. Однако нет механизма для создания составного исключения, которое будут обрабатывать оба обработчика.Foo
может различать исключение, котороеFoo
либо выдает себя, либо намеренно хочет притвориться, что оно выбрасывает сам, от того, котороеFoo
не ожидалось, когда оно было вызывая какой-то другой метод. Это то, что понятие «проверенных» исключений должно быть «примерно».Легко можно смоделировать необработанное исключение в текущем потоке. Это вызовет обычное поведение необработанного исключения и, таким образом, выполнит работу семантически. Это, однако, не обязательно остановит выполнение текущего потока, так как никакое исключение фактически не выдается.
Это действительно полезно в (очень редких) ситуациях, например, когда
Error
требуется правильная обработка, но метод вызывается из каркаса, перехватывающего (и отбрасывающего) любойThrowable
.источник
Вызовите System.exit (1) в
finalize
и просто сгенерируйте копию исключения из всех других методов, чтобы программа завершилась.источник