Checked Exception loophole

R

Roedy Green

When I call a method via an interface reference rather than a class
reference, all the checked exceptions it could throw will not
necessarily be known.

So the calling method won't know to use a try block or declare throws
xxxx.

This occurred to me just as I was drifting off to sleep. Is there
some flaw in my thinking or is this a giant loophole in the Exception
structure?
 
A

Arne Vajhøj

Roedy said:
When I call a method via an interface reference rather than a class
reference, all the checked exceptions it could throw will not
necessarily be known.

So the calling method won't know to use a try block or declare throws
xxxx.

This occurred to me just as I was drifting off to sleep. Is there
some flaw in my thinking or is this a giant loophole in the Exception
structure?

You can not do that - the compiler will complain about the
signature being different.

Arne
 
S

Stefan Ram

Roedy Green said:
When I call a method via an interface reference rather than a class
reference, all the checked exceptions it could throw will not
necessarily be known.

They are deemed part of the interface of a method, so they need
to be declared within interfaces declarations.

If one does not want to declare so many variants of an
interface for all possible combinations of checked exceptions,
type parameters can be used within an interface for the
exceptions thrown. One can provide, say, two type parameters
for checked exceptions, and instantiate unsued type parameters
with »RuntimeException«.

For example,

interface Value<V, E1 extends Throwable, E2 extends Throwable>
{ V value() throws E1, E2; }

Convenience classes, when less than two exceptions are needed:

interface Value1CE<V, E1 extends Throwable>
extends Value<V, E1, RuntimeException> {}

interface ValueNoCE<V> extends Value1CE<V, RuntimeException> { }

This is based on a post by Ralf Ullrich:

<[email protected]>

http://groups.google.com/group/de.c...b202f65760cc?hl=de&dmode=source&output=gplain
 
T

Tom Anderson

When I call a method via an interface reference rather than a class
reference, all the checked exceptions it could throw will not
necessarily be known.

Not so. As a wise sage once said, ask the compiler. What happens if you
try it?
This occurred to me just as I was drifting off to sleep. Is there some
flaw in my thinking or is this a giant loophole in the Exception
structure?

Flaw, i'm afraid. The thoughts that come to us when we're drifting off to
sleep are often ones that would make perfect sense in a slightly different
world, but sadly not in ours.

tom
 
D

Daniel Pitts

Roedy said:
When I call a method via an interface reference rather than a class
reference, all the checked exceptions it could throw will not
necessarily be known.

So the calling method won't know to use a try block or declare throws
xxxx.
No, an implementer can't throw an exception not declared by the interface.
This occurred to me just as I was drifting off to sleep. Is there
some flaw in my thinking or is this a giant loophole in the Exception
structure?
No, the giant loopwhole is:

public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}
 
R

Roedy Green

Flaw, i'm afraid.

I'm very glad to hear that. It was a feeling like the floor being
yanked out from under me, and a need to reexamine all my code. I'm
glad to hear it works the way it should.
 
T

Tom Anderson

No, the giant loopwhole is:

public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:



NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning



And hopefully this will be fixed in the future. There used to a similar
loophole with Class.newInstance - if a constructor threw a checked
exception, it would emerge from the newInstance call intact. No
InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check if the
argument is an Error or RuntimeException, and if it isn't, just throw an
IllegalArgumentException instead!

tom
 
D

Daniel Pitts

Tom said:
No, the giant loopwhole is:

public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:



NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in
java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning



And hopefully this will be fixed in the future. There used to a similar
loophole with Class.newInstance - if a constructor threw a checked
exception, it would emerge from the newInstance call intact. No
InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check if
the argument is an Error or RuntimeException, and if it isn't, just
throw an IllegalArgumentException instead!

tom
The easy fix would be to remove the method completely. It's been
deprecated for so long (along with some of the other dangerous Thread
methods) that it should be removed. Anyone who is relying on it
deserves a broken build at this point :).
 
A

Arne Vajhøj

Daniel said:
Tom said:
No, the giant loopwhole is:

public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:

NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in
java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning

And hopefully this will be fixed in the future. There used to a
similar loophole with Class.newInstance - if a constructor threw a
checked exception, it would emerge from the newInstance call intact.
No InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check if
the argument is an Error or RuntimeException, and if it isn't, just
throw an IllegalArgumentException instead!
The easy fix would be to remove the method completely. It's been
deprecated for so long (along with some of the other dangerous Thread
methods) that it should be removed. Anyone who is relying on it
deserves a broken build at this point :).

It would ruin one of Java strengths: old code keeps working.

Arne
 
D

Daniel Pitts

Arne said:
Daniel said:
Tom said:
public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:

NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in
java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning

And hopefully this will be fixed in the future. There used to a
similar loophole with Class.newInstance - if a constructor threw a
checked exception, it would emerge from the newInstance call intact.
No InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check if
the argument is an Error or RuntimeException, and if it isn't, just
throw an IllegalArgumentException instead!
The easy fix would be to remove the method completely. It's been
deprecated for so long (along with some of the other dangerous Thread
methods) that it should be removed. Anyone who is relying on it
deserves a broken build at this point :).

It would ruin one of Java strengths: old code keeps working.

Arne
Not in this case. Old code keeps compiling. Code that relied on this
never worked in the first place.
 
A

Arne Vajhøj

Daniel said:
Arne said:
Daniel said:
Tom Anderson wrote:
public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:

NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in
java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning

And hopefully this will be fixed in the future. There used to a
similar loophole with Class.newInstance - if a constructor threw a
checked exception, it would emerge from the newInstance call intact.
No InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check
if the argument is an Error or RuntimeException, and if it isn't,
just throw an IllegalArgumentException instead!

The easy fix would be to remove the method completely. It's been
deprecated for so long (along with some of the other dangerous Thread
methods) that it should be removed. Anyone who is relying on it
deserves a broken build at this point :).

It would ruin one of Java strengths: old code keeps working.
Not in this case. Old code keeps compiling. Code that relied on this
never worked in the first place.

If you remove a method then old code calling that method does
not compile.

Arne
 
C

Christian

Tom said:
No, the giant loopwhole is:

public void noCheckedExceptions() {
Thread.currentThread().stop(new Exception());
}

Yikes. I didn't know about that one.

To be fair, trying this under 1.5 at least gets me:



NCE.java:3: warning: [deprecation] stop(java.lang.Throwable) in
java.lang.Thread has been deprecated
Thread.currentThread().stop(new Exception());
^
1 warning



And hopefully this will be fixed in the future. There used to a similar
loophole with Class.newInstance - if a constructor threw a checked
exception, it would emerge from the newInstance call intact. No
InvocationTargetExceptions in those days!

You know, the easiest fix for Thread.stop would be for it to check if
the argument is an Error or RuntimeException, and if it isn't, just
throw an IllegalArgumentException instead!

tom

there are still possibilities that aren't deprecated:
This class lets you throw an exception without need for declaration.
Uses weakness in .newInstance() method. ugly ugly .. be sure you wash
out your eyes after reading it!

public class Thrower {
private static Throwable t;

private Thrower() throws Throwable {
throw t;
}

public static synchronized void sneakyThrow(Throwable t) {
Thrower.t = t;
try {
Thrower.class.newInstance();
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} finally {
Thrower.t = null;
}
}
}


the other way possible is by exploiting enums only checked at compile
time.. though that gives you at least an unchecked cast warning:

public class TigerThrower<T extends Throwable> {
public static void sneakyThrow(Throwable t) {
new TigerThrower<Error>().sneakyThrow2(t);
}

private void sneakyThrow2(Throwable t) throws T {
throw (T) t;
}
}


Christian
 
D

Daniel Pitts

Arne said:
If you remove a method then old code calling that method does
not compile.
Sorry, I jumped horse in mid sentance...I meant that one of Java "strenghts" is that old code keeps compiling,
not necessary "keeps working". I don't think this is necessarily a
strength. I think that the goal should be a "mostly stable" library.
where deprecation actually has meaning. If I upgrade between major
versions, I shouldn't expect that all deprecated items in the old
version will work at all in the newer version.

The other *separate* point that I was making was that code relying on
Thread.stop() is broken to begin with, so making it fail to compile is
appropriate.
 
A

Arne Vajhøj

Daniel said:
Sorry, I jumped horse in mid sentance...
I meant that one of Java "strenghts" is that old code keeps compiling,
not necessary "keeps working". I don't think this is necessarily a
strength. I think that the goal should be a "mostly stable" library.
where deprecation actually has meaning. If I upgrade between major
versions, I shouldn't expect that all deprecated items in the old
version will work at all in the newer version.

A lot of Java customers prefer the "work forever".
The other *separate* point that I was making was that code relying on
Thread.stop() is broken to begin with, so making it fail to compile is
appropriate.

A lot of code is "broken" but is non the less running in production.

Arne
 
A

Arne Vajhøj

Bernie said:
Of course, but this is where the part about "major versions" comes in.
People running critical production code don't upgrade major versions
lightly, and they expect some shakedown problems when they do so.

True. But they still prefer less work over more work.
This
wouldn't even affect binary compatibility of existing apps anyway,

If they call a method that no longer exist, then it will effect the app.
so
they could even continue to build with the old compiler and run on the
new VM.

Combining "removing old methods" and "build on old version and deploy
on new version" is a good recipe for disaster. There is only one
thing that is worse than getting build errors due to removed methods
and that is not get building errors.
It would merely be a statement "if you want to take advantage of
the new features of version X+1, you should fix problems deprecated
since version X-2 or so". I at least do not see this as breaking any
compatibility guarantee and I think it would be a benefit to all
stakeholders.

Not for those companies that has to spend dollars making the changes.

Arne
 
T

Tom Anderson

there are still possibilities that aren't deprecated:
This class lets you throw an exception without need for declaration. Uses
weakness in .newInstance() method. ugly ugly .. be sure you wash out your
eyes after reading it!

Aieee! That's the loophole i was talking about! I thought they'd closed
that!

tom
 
D

Daniel Pitts

Arne said:
Not for those companies that has to spend dollars making the changes.

Arne
Those companies can choose not to upgrade, or can choose to improve
there product along the way. Oh, and it *is* a myth that upgrading
JVM/JDK versions won't break anything. I just think that it should
break the right things :).
 
A

Arne Vajhøj

Daniel said:
Those companies can choose not to upgrade,

Then they can not utilize the new things.
or can choose to improve
there product along the way.

Companies usually prefer to spend their money delivering new
functionality to the customers instead of making the
existing code build and run with a new Java.
Oh, and it *is* a myth that upgrading
JVM/JDK versions won't break anything.

That is not my experience. So far Java has a pretty good track record
regarding this.

Arne
 
D

Daniel Pitts

Arne said:
Then they can not utilize the new things.


Companies usually prefer to spend their money delivering new
functionality to the customers instead of making the
existing code build and run with a new Java.


That is not my experience. So far Java has a pretty good track record
regarding this.
Perhaps with the projects you have, buts where I work we have several
projects stuck in Java 1.4, because upgrading is too "expensive" in man
power. It may be true for "smaller" projects, but projects that have
high cost for regression bugs can't rely on upgrades not breaking
things. Or maybe the company I work for is just paranoid :)
 
A

Arne Vajhøj

Daniel said:
Perhaps with the projects you have, buts where I work we have several
projects stuck in Java 1.4, because upgrading is too "expensive" in man
power. It may be true for "smaller" projects, but projects that have
high cost for regression bugs can't rely on upgrades not breaking
things. Or maybe the company I work for is just paranoid :)

You always test if you make any changes, so you always has the cost
of retesting when upgrading.

It does not prove that backwards compatibility is a myth. Even
if there had been zero upgrade problems from 1.0 to current, then
test would still be required.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top