[java] 잡을 수없는 척

가설을 포착 할 수 없게하는 코드 스 니펫을 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.

“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그러나 그것은 하나의 버섯 구름을 낳는 어머니 예외이기 때문에 척 대신 이름을 지정했습니다 . 또한, 당신이 생각했던 것과 정확히 일치하지는 않지만 확실히 잡을 수는 없습니다. 관찰 :

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)
    {

    }
}

스택 오버플로가 발생합니다. 다시 예외가 포착되지 않습니다.


답변

이러한 예외가있는 경우 분명히 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

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