programing tip

잡을 수없는 ChuckNorrisException

itbloger 2020. 10. 3. 10:05
반응형

잡을 수없는 ChuckNorrisException


가설을 잡을 수 없게 만드는 코드 조각을 Java 로 구성 할 수 java.lang.ChuckNorrisException있습니까?

떠오른 생각은 예를 들어 인터셉터 또는 측면 지향 프로그래밍을 사용하고 있습니다.


경우 나도 몰라 그래서 나는이 시도하지 않은 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.

"extends 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"

이것을 숙고 한 후에 나는 잡을 수없는 예외를 성공적으로 만들었다. JulesWinnfield그러나 나는 버섯 구름을 낳는 어머니의 예외이기 때문에 Chuck이 아니라 이름을 지정했습니다 . 더욱이 그것은 당신이 생각했던 것과 정확히 일치하지 않을 수도 있지만 확실히 잡힐 수는 없습니다. 관찰 :

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");
    }
}

Et voila! 포착되지 않은 예외입니다.

산출:

운영:

다시 '무엇'이라고 말하세요! 감히! 나는 당신을 두 배로 감히!

자바 결과 : 8

BUILD SUCCESSFUL (총 시간 : 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)
    {

    }
}

스택 오버플로가 발생합니다. 다시 예외가 잡히지 않은 상태로 유지됩니다.


이러한 예외 System.exit(Integer.MIN_VALUE);가있는 경우 생성자에서 를 사용하는 것은 분명히 필수입니다. 왜냐하면 그러한 예외를 던지면 발생하는 일이기 때문입니다.)


모든 코드는 Throwable을 잡을 수 있습니다. 따라서 어떤 예외를 생성하든 Throwable의 하위 클래스가되어 포착 될 수 있습니다.


public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}

( 기술적 으로이 예외는 실제로 발생하지 않지만 적절한 예외는 ChuckNorrisException발생할 수 없습니다. 먼저 발생합니다.)


던지는 모든 예외는 Throwable을 확장해야하므로 항상 잡을 수 있습니다. 그래서 대답은 아니오입니다.

당신이 그것을 어렵게 처리 할 수 있도록하려는 경우, 당신은 방법을 대체 할 수 있습니다 getCause(), getMessage(), getStackTrace(), toString()서로를 던져 java.lang.ChuckNorrisException.


내 대답은 @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

놀랍지 않습니다-결국 라운드 하우스 킥입니다 :)


생성자에서 반복적으로 호출하는 스레드를 시작할 수 있습니다. originalThread.stop (ChuckNorisException.this)

스레드는 예외를 반복적으로 포착 할 수 있지만 죽을 때까지 계속 발생시킵니다.


No. All exceptions in Java must subclass java.lang.Throwable, and although it may not be good practice, you can catch every type of exception like so:

try {
    //Stuff
} catch ( Throwable T ){
    //Doesn't matter what it was, I caught it.
}

See the java.lang.Throwable documentation for more information.

If you're trying to avoid checked exceptions (ones that must be explicitly handled) then you will want to subclass Error, or RuntimeException.


Actually the accepted answer is not so nice because Java needs to be run without verification, i.e. the code would not work under normal circumstances.

AspectJ to the rescue for the real solution!

Exception class:

package de.scrum_master.app;

public class ChuckNorrisException extends RuntimeException {
    public ChuckNorrisException(String message) {
        super(message);
    }
}

Aspect:

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;
    }
}

Sample application:

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!");
    }
}

Output:

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)

A variant on the theme is the surprising fact that you can throw undeclared checked exceptions from Java code. Since it is not declared in the methods signature, the compiler won't let you catch the exception itself, though you can catch it as java.lang.Exception.

Here's a helper class that lets you throw anything, declared or not:

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;
  }
}

Now throw SneakyThrow.sneak(new ChuckNorrisException()); does throw a ChuckNorrisException, but the compiler complains in

try {
  throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}

about catching an exception that is not thrown if ChuckNorrisException is a checked exception.


The only ChuckNorrisExceptions in Java should be OutOfMemoryError and StackOverflowError.

You can actually "catch" them in the means that a catch(OutOfMemoryError ex) will execute in case the exception is thrown, but that block will automatically rethrow the exception to the caller.

I don't think that public class ChuckNorrisError extends Error does the trick but you could give it a try. I found no documentation about extending Error


Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?

Yes, and here's the answer: Design your java.lang.ChuckNorrisException such that it is not an instance of java.lang.Throwable. Why? An unthrowable object is uncatchable by definition because you can never catch something that can never be thrown.


You can keep ChuckNorris internal or private and encapsulate him or swollow him...

try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }


Two fundamental problems with exception handling in Java are that it uses the type of an exception to indicate whether action should be taken based upon it, and that anything which takes action based upon an exception (i.e. "catch"es it) is presumed to resolve the underlying condition. It would be useful to have a means by which an exception object could decide which handlers should execute, and whether the handlers that have executed so far have cleaned things up enough for the present method to satisfy its exit conditions. While this could be used to make "uncatchable" exceptions, two bigger uses would be to (1) make exceptions which will only be considered handled when they're caught by code that actually knows how to deal with them, and (2) allow for sensible handling of exceptions which occur in a finally block (if a FooException during a finally block during the unwinding of a BarException, both exceptions should propagate up the call stack; both should be catchable, but unwinding should continue until both have been caught). Unfortunately, I don't think there would be any way to make existing exception-handling code work that way without breaking things.


It is easily possible to simulate a uncaught exception on the current thread. This will trigger the regular behavior of an uncaught exception, and thus gets the job done semantically. It will, however, not necessarily stop the current thread's execution, as no exception is actually thrown.

Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
    currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.

This is actually useful in (very rare) situations, for example when proper Error handling is required, but the method is invoked from a framework catching (and discarding) any Throwable.


Call System.exit(1) in the finalize, and just throw a copy of the exception from all the other methods, so that the program will exit.

참고URL : https://stackoverflow.com/questions/13883166/uncatchable-chucknorrisexception

반응형