Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What on earth is "Self-suppression not permitted" and why is Javac generating code which results in this error?

This new Java 7 try-with-resources construct is quite nice. Or at least, it was nice until an exception came along and ruined my day.

I've finally managed to boil it down to a reproducible test which uses nothing but JUnit+jMock.

@Test
public void testAddSuppressedIssue() throws Exception {
    Mockery mockery = new Mockery();
    final Dependency dependency = mockery.mock(Dependency.class);

    mockery.checking(new Expectations() {{
        allowing(dependency).expectedCall();
        allowing(dependency).close();
    }});

    try (DependencyUser user = new DependencyUser(dependency)) {
        user.doStuff();
    }
}

// A class we're testing.
private static class DependencyUser implements Closeable {
    private final Dependency dependency;

    private DependencyUser(Dependency dependency) {
        this.dependency = dependency;
    }

    public void doStuff() {
        dependency.unexpectedCall(); // bug
    }

    @Override
    public void close() throws IOException {
        dependency.close();
    }
}

// Interface for its dependent component.
private static interface Dependency extends Closeable {
    void expectedCall();
    void unexpectedCall();
}

Running this example, I get:

java.lang.IllegalArgumentException: Self-suppression not permitted
    at java.lang.Throwable.addSuppressed(Throwable.java:1042)
    at com.acme.Java7FeaturesTest.testTryWithResources(Java7FeaturesTest.java:35)

Reading the documentation, they seem to be saying that if you were to add a suppressed exception back to itself, that is what triggers this error. But I'm not doing that, I'm just using a try-with-resources block. The Java compiler then generates what would seem to be illegal code, which makes the feature effectively unusable.

Of course, when the test passes, no problem occurs. And when the test fails, an exception occurs. So now that I have fixed the problem I originally discovered I have reverted to using try-with-resources. But next time an exception occurs, I would much rather the exception be the expectation failure, instead of one Java itself has emitted for seemingly no good reason.

So... is there a way to get proper error reporting here, without giving up on try-with-resources?

like image 782
Hakanai Avatar asked Aug 24 '12 04:08

Hakanai


People also ask

Why does the command prompt refuse to identify the javac command?

When we type the command in the Command Prompt, the prompt refuse to identify the javac command. It means that the javac.exe file is not found by the compiler. The javac.exe file exists in the bin folder of the JDK installation folder. The error we get because the PATH is not properly set.

Why is javac not working on Windows 10?

Fix: Javac is not recognized on Windows 10 “ Javac is not recognized as an internal or external command ” is an error often encountered by people trying to compile Java programs on Windows using Command Prompt. It’s might also be encountered when users try to check the current version of the primary Java compiler.

What does javac is not recognized as internal or external command?

Before moving ahead in this section, let's understand the meaning of the error statement javac is not recognized as internal or external command. In Java, javac is a command that compiles the Java source code. When we type the command in the Command Prompt, the prompt refuse to identify the javac command.

How to test the javac command is working properly?

To test it is working properly or not, open the Command Prompt and type javac command and press the enter key. The command shows the options that we can use with the javac command.


1 Answers

It looks like jMock throws the same instance of exception from the both methods. That's how it can be reproduced without jMock:

public class Test implements Closeable {
    private RuntimeException ex = new RuntimeException();

    public void doStuff() {
        throw ex;
    }

    public void close() {
        throw ex;
    }
}

try (Test t = new Test()) {
    t.doStuff();
}

If so, I think it's a problem of jMock rather than of Java compiler.

like image 145
axtavt Avatar answered Sep 27 '22 21:09

axtavt