Exception transparency - lone throws (no checked exceptions)

Reinier Zwitserloot reinier at zwitserloot.com
Thu Jun 10 18:39:47 PDT 2010


Where did I claim it removes the ability to _use_ checked exceptions?
Offering a way to opt out of them is more than enough to irk some wraths.

Updating SAM classes is obviously a big problem. There's are a few bajillion
SAM classes out there in the greater java community, and oracle can only
update those in rt.jar. With the update to the SAM class, there's also a
semantic difference, which may be important. I mentioned it in my more
detailed proposal (folks presuming that if a block containing X statements
throws checked exception of type E, that only the method calls to methods
declaring throws E could possibly be the source of that exception, which
ceases to be true in the face of lone throws) - but it's much bigger issue
when lone throws is legal anywhere.

--Reinier Zwitserloot



On Thu, Jun 10, 2010 at 11:34 PM, Alessio Stalla <alessiostalla at gmail.com>wrote:

> On Thu, Jun 10, 2010 at 8:31 PM, Reinier Zwitserloot
> <reinier at zwitserloot.com> wrote:
> > SneakyThrows is possible in the following ways:
> >
> > 1. Use any non-java JVM language, such as scala, jython, or JRuby. None
> of
> > these languages have the concept 'checked exception', and neither does
> the
> > JVM ('throws' lists are of course in class files, but as far as the JVM
> is
> > concerned these are like annotations; the JVM does nothing with them
> other
> > than let you introspect the list). You can sneakythrow anything using
> this
> > tactic. In the end all you need to do is create a class file with a
> method
> > that does not have a 'throws' list but which does use the "ATHROW" opcode
> to
> > throw a checked exception. The class verifier nor the JVM runtime
> complains
> > about doing this; this is why jython, scala, etc all can compile just
> fine
> > without having the notion of checked exceptions.
> >
> > 2. Use MyClass.class.newInstance() - if MyClass's no-args constructor
> throws
> > a checked exception it will be sneakythrown onwards. The only two you
> can't
> > sneak with this are those checked exceptions that newInstance() itself
> > declares; InstantiationException and IllegalAccessException. This is the
> > reflection library oversight that Florian was talking about, I believe.
> It's
> > also the only one; both Method and Constructor's invoke/newInstance
> methods
> > solved this problem by wrapping exceptions into
> InvocationTargetException.
> > It's only Class.newInstance() that doesn't do this.
> >
> > 3. Use mixed class files. Compile "public class Sneaky { public static
> void
> > sneaky(Throwable t) { /* do nothing */ }}", then compile your code
> against
> > this class file, but at runtime, recompile *ONLY* Sneaky.class with this:
> > "public class Sneaky { public static void sneaky(Throwable t) throws
> > Throwable { throw t; }}". The JVM doesn't check if a method's signature's
> > addendums, such as the throws clauses, are still the same as they were
> when
> > you compiled against the API, so this works just fine. In practice you'd
> > have 2 sneakies, compile against the one, but use the other for runtime.
> >
> > 4. Generics:
> >
> > public class Sneaky {
> > public static void sneaky(Throwable t) {
> >  Sneaky.<RuntimeException>sneaky0(t);
> > }
> >
> > @SuppressWarnings("unchecked")
> > private static <T extends Throwable> void sneaky0(Throwable t) throws T {
> > throw (T)t;
> > }
> > }
> >
> >
> >
> > As far as I know these are the only ways, but its clear that one simply
> > cannot assume sneaky throws just don't happen; in particular assuming
> that
> > mixed class files or class files compiled by alternative languages never
> > happen is a bad idea.
> >
> > Stephen: I wouldn't particularly mind your proposal, personally, but it's
> > effectively aborting the checked exception experiment.
>
> No, it's not. It doesn't forbid checked exceptions or change their
> semantics. It gives the power to an API writer to allow you to ignore
> checked exceptions coming from the API methods. API writers already
> have this power today: they just need to explicitly wrap checked
> exceptions in unchecked ones. Spring, for example, does this
> extensively. "lone throws" simply make this option easier.
>
> > I'm okay with it
> > (heck, I tossed @SneakyThrows in lombok for a reason!) but from my
> > experiences with @SneakyThrows, there are lots and lots of java
> programmers
> > that have been ingrained with the notion that checked exceptions are what
> > keeps the world from imploding and will vehemently fight for them. Just a
> > friendly heads up :) There's an alternative implementation which is based
> on
> > explicitly stating the types you'd like to sneaky throw. I'm not quite
> sure
> > how one would mesh this with the closure syntax, but it has the advantage
> of
> > at least explicitly stating that, yes, I 'sneaky' throw IOException here.
> > Lombok's SneakyThrow works like this:
> >
> > @SneakyThrows(IOException.class)
> > public void foo() { throw new IOException(); }
> >
> > with just "@SneakyThrows" being a shorthand for
> > @SneakyThrows(Throwable.class). In regards to closures I believe your
> > proposal to be superior, if we go down this "let's give up on checked
> > exceptions" path.
> >
> > However, your proposal has a flaw; I think it'll eventually boil down to
> > simply getting rid of the concept of checked exceptions in general. It
> > doesn't extend to SAMs, because in your system adding a "lone throws"
> > changes the signature.
>
> Right, but it changes it in such a way that old code will continue to
> work unchanged. If Runnable.run was changed to include throws; you
> could still call it without catching anything, as you do today.
>
> > You can add a lone throws to an interface method
> > without breaking backwards compatibility as far as I can tell, but that's
> > not the problem. The problem is this: *Existing* SAM classes that aren't
> > updated to add a lone throws to their one abstract method CANNOT be
> created
> > by way of the closure syntax, because closures have implicit lone throws.
>
> Then update the SAM classes, what's the problem if the update is
> backwards-compatible? Are you thinking about user classes here? In
> that case, the user is responsible to update the classes if she wants
> them to be compatible with closures that can throw exceptions. They
> would need to be updated anyway if the closure declared to throw
> checked exceptions while the SAM class didn't. Or am I missing
> something?
>
> Regards,
> Alessio Stalla
>


More information about the lambda-dev mailing list