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?

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.


Need Your Help

How to remove gap in java swing label of large size

java swing jlabel

in my application I have label which has a font size over 200. This label contains big up and down (irregular)gap. How can I remove it ?

Remove quotes from named environment variables in Windows scripts

windows batch-file scripting environment-variables quotes

I want to store a URL prefix in an Windows environment variable. The ampersands in the query string makes this troublesome though.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.