가설을 포착 할 수 없게하는 코드 스 니펫을 Java 로 구성 할 수 java.lang.ChuckNorrisException
있습니까?
염두에 둔 생각은 예를 들어 인터셉터 또는 화면 지향 프로그래밍을 사용 합니다.
finalize()
어떻습니까?
가설을 포착 할 수 없게하는 코드 스 니펫을 Java 로 구성 할 수 java.lang.ChuckNorrisException
있습니까?
염두에 둔 생각은 예를 들어 인터셉터 또는 화면 지향 프로그래밍을 사용 합니다.
finalize()
어떻습니까?
답변:
경우 나도 몰라 그래서 나는이 시도하지 않은 JVM은 이 같은 제한,하지만 어쩌면 당신은 발생 코드를 컴파일 할 수 ChuckNorrisException
있지만, 실행시의 클래스 정의를 제공 ChuckNorrisException
하는 Throwable를 확장하지 않습니다 .
최신 정보:
작동하지 않습니다. 검증 자 오류를 생성합니다.
Exception in thread "main" java.lang.VerifyError: (class: TestThrow, method: ma\
in signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestThrow. Program will exit.
업데이트 2 :
실제로 바이트 코드 검증기를 비활성화하면이 기능을 사용할 수 있습니다! ( -Xverify:none
)
업데이트 3 :
집에서 다음과 같은 사람들을 위해 다음은 전체 스크립트입니다.
다음 클래스를 작성하십시오.
public class ChuckNorrisException
extends RuntimeException // <- Comment out this line on second compilation
{
public ChuckNorrisException() { }
}
public class TestVillain {
public static void main(String[] args) {
try {
throw new ChuckNorrisException();
}
catch(Throwable t) {
System.out.println("Gotcha!");
}
finally {
System.out.println("The end.");
}
}
}
컴파일 클래스 :
javac -cp . TestVillain.java ChuckNorrisException.java
운영:
java -cp . TestVillain
Gotcha!
The end.
"RuntimeException을 확장"과 주석 재 컴파일 ChuckNorrisException.java
만 :
javac -cp . ChuckNorrisException.java
운영:
java -cp . TestVillain
Exception in thread "main" java.lang.VerifyError: (class: TestVillain, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestVillain. Program will exit.
확인없이 실행 :
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
Object
대신에 잡으면 Throwable
어떨까? (컴파일러는 허용하지 않지만, 이미 검증기를 비활성화했기 때문에 바이트 코드를 해킹하여이를 수행 할 수도 있습니다.)
이것을 숙고 한 후, 나는 잡을 수없는 예외를 성공적으로 만들었습니다. JulesWinnfield
그러나 그것은 하나의 버섯 구름을 낳는 어머니 예외이기 때문에 척 대신 이름을 지정했습니다 . 또한, 당신이 생각했던 것과 정확히 일치하지는 않지만 확실히 잡을 수는 없습니다. 관찰 :
public static class JulesWinnfield extends Exception
{
JulesWinnfield()
{
System.err.println("Say 'What' again! I dare you! I double dare you!");
System.exit(25-17); // And you shall know I am the LORD
}
}
public static void main(String[] args)
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
System.out.println("There's a word for that Jules - a bum");
}
}
짜잔! 잡히지 않은 예외.
산출:
운영:
'무엇을 다시 말해봐! 감히! 나는 당신을 두 번 감히!
자바 결과 : 8
빌드 성공 (총 시간 : 0 초)
시간이 좀 더 있으면 다른 것을 생각 해낼 수 없는지 알게 될 것입니다.
또한 이것을 확인하십시오 :
public static class JulesWinnfield extends Exception
{
JulesWinnfield() throws JulesWinnfield, VincentVega
{
throw new VincentVega();
}
}
public static class VincentVega extends Exception
{
VincentVega() throws JulesWinnfield, VincentVega
{
throw new JulesWinnfield();
}
}
public static void main(String[] args) throws VincentVega
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
}
catch(VincentVega vv)
{
}
}
스택 오버플로가 발생합니다. 다시 예외가 포착되지 않습니다.
JulesWinfield
합니까? 던지기 전에 시스템이 멈춰 서지 않습니까?
throw new Whatever()
은 실제로 두 부분으로 구성 Whatever it = new Whatever(); throw it;
되며 시스템은 두 번째 부분에 도달하기 전에 죽습니다.
class cn extends exception{private cn(){}}
이러한 예외가있는 경우 분명히 System.exit(Integer.MIN_VALUE);
생성자 를 사용하는 것이 필수적입니다. 왜냐하면 이러한 예외를 던지면 발생할 수 있기 때문입니다.)
while(true){}
대신 사용할 수 있습니다 System.exit()
.
System.exit()
를 허용하지 보안 관리자를 설치하여 작동. 생성자를 다른 예외 (SecurityException)로 바꾸면 잡힐 수 있습니다.
모든 코드는 Throwable을 잡을 수 있습니다. 따라서, 당신이 만든 예외는 Throwable의 서브 클래스가되고 잡힐 수 있습니다.
hang
ChuckNorrisException을 포착하려는 시도에서 Throwable 자체가 발생합니다. : P
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
( 기술적 으로이 예외는 실제로 발생하지 않지만 적절한 ChuckNorrisException
것을 던질 수는 없습니다. 먼저 먼저 던집니다.)
던지는 예외는 Throwable을 확장해야하므로 항상 잡을 수 있습니다. 따라서 대답은 '아니요'입니다.
당신이 그것을 어렵게 처리 할 수 있도록하려는 경우, 당신은 방법을 대체 할 수 있습니다 getCause(), getMessage()
, getStackTrace()
, toString()
서로를 던져 java.lang.ChuckNorrisException
.
catch(Throwable t)
사용자가 예외에 대처하고자 할 때 나의 제안은 다음 블록에서 적용 할 수 있도록 변수로 만 저장합니다
내 대답은 @jtahlborn의 아이디어를 기반으로하지만 완전히 작동하는 Java 프로그램이며 JAR 파일 로 패키지화되고 웹 응용 프로그램 의 일부로 즐겨 사용하는 응용 프로그램 서버에 배포 할 수 있습니다 .
우선 ChuckNorrisException
, 처음부터 JVM이 충돌하지 않도록 클래스를 정의합시다 (Chuck은 충돌하는 JVM BTW를 정말로 좋아합니다 :)
package chuck;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
}
@Override
public Throwable getCause() {
return null;
}
@Override
public String getMessage() {
return toString();
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
}
@Override
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
}
}
이제 Expendables
클래스를 구성하여 구성합니다.
package chuck;
import javassist.*;
public class Expendables {
private static Class clz;
public static ChuckNorrisException getChuck() {
try {
if (clz == null) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("chuck.ChuckNorrisException");
cc.setSuperclass(pool.get("java.lang.Object"));
clz = cc.toClass();
}
return (ChuckNorrisException)clz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
그리고 마지막으로 Main
수업에서 엉덩이를 걷어차십시오.
package chuck;
public class Main {
public void roundhouseKick() throws Exception {
throw Expendables.getChuck();
}
public void foo() {
try {
roundhouseKick();
} catch (Throwable ex) {
System.out.println("Caught " + ex.toString());
}
}
public static void main(String[] args) {
try {
System.out.println("before");
new Main().foo();
System.out.println("after");
} finally {
System.out.println("finally");
}
}
}
다음 명령으로 컴파일하고 실행하십시오.
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
다음과 같은 출력이 나타납니다.
before
finally
놀랍지 않습니다-결국 라운드 하우스 킥입니다 :)
아니요. Java의 모든 예외는 서브 클래스 여야하며 java.lang.Throwable
, 모범 사례는 아니지만 모든 유형의 예외를 다음과 같이 잡을 수 있습니다.
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
자세한 정보는 java.lang.Throwable 문서를 참조하십시오.
확인 된 예외 (명시 적으로 처리 해야하는 예외) 를 피하려는 경우 Error 또는 RuntimeException을 서브 클래스 화하려고합니다.
실제로 승인 된 답변은 Java가 검증없이 실행되어야하기 때문에 좋지 않습니다. 즉, 정상적인 상황에서는 코드가 작동하지 않습니다.
실제 솔루션을 구하기위한 AspectJ !
예외 클래스 :
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
public ChuckNorrisException(String message) {
super(message);
}
}
양상:
package de.scrum_master.aspect;
import de.scrum_master.app.ChuckNorrisException;
public aspect ChuckNorrisAspect {
before(ChuckNorrisException chuck) : handler(*) && args(chuck) {
System.out.println("Somebody is trying to catch Chuck Norris - LOL!");
throw chuck;
}
}
샘플 애플리케이션 :
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
catchAllMethod();
}
private static void catchAllMethod() {
try {
exceptionThrowingMethod();
}
catch (Throwable t) {
System.out.println("Gotcha, " + t.getClass().getSimpleName() + "!");
}
}
private static void exceptionThrowingMethod() {
throw new ChuckNorrisException("Catch me if you can!");
}
}
산출:
Somebody is trying to catch Chuck Norris - LOL!
Exception in thread "main" de.scrum_master.app.ChuckNorrisException: Catch me if you can!
at de.scrum_master.app.Application.exceptionThrowingMethod(Application.java:18)
at de.scrum_master.app.Application.catchAllMethod(Application.java:10)
at de.scrum_master.app.Application.main(Application.java:5)
테마의 변형은 Java 코드에서 선언되지 않은 검사 예외를 던질 수 있다는 놀라운 사실입니다. 메소드 서명에 선언되어 있지 않기 때문에 컴파일러는 예외 자체를 잡을 수는 없지만 java.lang.Exception으로 잡을 수는 있습니다.
다음은 선언 여부에 관계없이 무언가를 던질 수있는 도우미 클래스입니다.
public class SneakyThrow {
public static RuntimeException sneak(Throwable t) {
throw SneakyThrow.<RuntimeException> throwGivenThrowable(t);
}
private static <T extends Throwable> RuntimeException throwGivenThrowable(Throwable t) throws T {
throw (T) t;
}
}
이제 throw SneakyThrow.sneak(new ChuckNorrisException());
ChuckNorrisException이 발생하지만 컴파일러는
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
ChuckNorrisException이 확인 된 예외 인 경우 발생하지 않는 예외를 잡는 방법
ChuckNorrisException
Java에서 유일한 것은 OutOfMemoryError
and 이어야합니다 StackOverflowError
.
실제로 catch(OutOfMemoryError ex)
예외가 발생하는 경우 a 가 실행 된다는 의미에서 "캐치"할 수 있지만 해당 블록은 자동으로 예외를 호출자에게 다시 던집니다.
나는 그것이 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
예외가 될 혼자 throw 가능 객체를 할 수 있어야합니다
ChuckNorris를 내부 또는 개인으로 유지하고 캡슐화하거나 부어 넣을 수 있습니다 ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
Java에서 예외 처리의 두 가지 근본적인 문제점은 예외 유형을 사용하여 조치를 수행해야하는지 여부를 표시하고 예외를 기반으로 조치를 취하는 항목 (예 : "캐치")이 해결 될 것으로 추정된다는 것입니다. 기본 조건. 예외 객체가 어떤 핸들러를 실행해야하는지, 지금까지 실행 한 핸들러가 현재 메소드가 종료 조건을 만족시킬만큼 충분히 정리했는지 여부를 결정할 수있는 수단을 갖는 것이 유용 할 것입니다. 이것은 "잡을 수없는"예외를 만드는 데 사용될 수 있지만, 두 가지 더 큰 용도는 (1) 예외를 처리하는 방법을 실제로 알고있는 코드에 의해 포착 될 때만 처리되는 예외를 만드는 것입니다.finally
FooException
finally
를 해제하는 동안 차단 BarException
하면 두 예외가 모두 호출 스택을 전파해야합니다. 둘 다 잡을 수 있어야하지만 둘 다 잡힐 때까지 풀어야합니다. 불행히도 기존의 예외 처리 코드를 방해하지 않고 작동시키는 방법이 없다고 생각합니다.
finally
이전 예외에서 블록을 정리하는 동안 예외가 발생하면 다른 예외가 없으면 예외가 코드가 처리하고 계속할 것으로 예상되는 것일 수 있습니다. 그러나 하나를 처리하고 다른 하나를 무시하는 것은 좋지 않습니다. 그러나 두 핸들러가 처리 할 복합 예외를 생성하는 메커니즘은 없습니다.
Foo
하는 예외와 구별 하는 호출 코드를 구별 할 수 있는 수단이 있어야한다는 것 Foo
입니다.Foo
이 때 발생하는 기대되지 않았습니다 다른 방법을 호출합니다. 이것이 "체크 된"예외의 개념이 "약"이어야하는 것입니다.
현재 스레드에서 포착되지 않은 예외를 쉽게 시뮬레이션 할 수 있습니다. 이것은 잡히지 않은 예외의 규칙적인 동작을 유발하여 작업을 의미 적으로 수행합니다. 그러나 실제로 예외가 발생하지 않으므로 현재 스레드의 실행을 반드시 중지하지는 않습니다.
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
예를 들어 적절한 Error
처리가 필요한 경우와 같이 (매우 드물게) 상황에서 실제로 유용 하지만, 메소드는 any를 포착 (및 삭제)하는 프레임 워크에서 호출됩니다 Throwable
.