Unreachable catch classes

Robert Fischer robert.fischer at smokejumperit.com
Thu May 26 02:53:33 UTC 2011


Some non-Java languages produce bytecode that lie about which
exceptions they throw, and so unmarked methods may throw
non-RuntimeException Exception instances from there, too.

For instance, this Groovy method:
  def bar() {
    throw new Exception("Away it goes!")
  }

compiles to this bytecode method:
  public java.lang.Object bar();
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: invokestatic  #24                 // Method
$getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
         3: astore_1
         4: aload_1
         5: ldc           #35                 // int 0
         7: aaload
         8: invokestatic  #39                 // Method
$get$$class$java$lang$Exception:()Ljava/lang/Class;
        11: ldc           #41                 // String Away it goes!
        13: invokeinterface #47,  3           // InterfaceMethod
org/codehaus/groovy/runtime/callsite/CallSite.callConstructor:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        18: checkcast     #49                 // class java/lang/Throwable
        21: athrow
        22: aconst_null
        23: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      22     0  this   LFoo;
      LineNumberTable:
        line 3: 4

Unless I'm missing something, there's no warning to code consuming
this method that a should-be-checked exception is thrown in this
method.

So, as someone who is using that code, it is in my best interest to
catch Exception (not just RuntimeException), because I may well see
Exception.

This "unreachable exception" stuff seems like a nice idea, but not
really feasible. I've taken to just ignoring the warnings.

~~ Robert.

On Wed, May 25, 2011 at 10:27 PM, David Holmes <David.Holmes at oracle.com> wrote:
> It hadn't occurred to me before but the "more precise rethrow" semantics are
> basically making the same invalid assumption about where checked exceptions
> can be thrown. Before if you catch Throwable and want to rethrow then you
> have to cast to an unchecked exception type, or else wrap with an unchecked
> exception type. Now you can catch Throwable and simply rethrow it -
> potentially letting an undeclared checked-exception to continue to make its
> escape.
>
> Now given that you could instead have only caught unchecked-exceptions, and
> the undeclared checked exception would have escaped anyway, this is perhaps
> not a big deal.
>
> But it troubles me that the language assumes things that are known to not be
> upheld by the libraries, and rather than helping to identify such cases this
> language change will now be helping to hide such cases.
>
> David
>
> David Holmes said the following on 04/28/11 22:03:
>>
>> Maurizio Cimadamore said the following on 04/28/11 21:56:
>>>
>>> On 27/04/11 13:51, Maurizio Cimadamore wrote:
>>>>
>>>> On 27/04/11 09:18, David Holmes wrote:
>>>>>
>>>>> Special-casing Throwable wouldn't be sufficient as people may use
>>>>> Exception instead.
>>>>
>>>> I guess this doesn't invalidate the argument - we could special-case
>>>> Exception AND Throwable, since they are already treated specially in the
>>>> language...
>>>>
>>>> Maurizio
>>>
>>> Hi
>>> after a discussion with the team, we have decided that we will relax the
>>> new javac warnings so that they will *not* be generated for those catch
>>> clauses catching Exception or Throwable.
>>>
>>> This is similar to how javac has always handled a similar case (error
>>> message: 'exception never thrown in body of try'); for example, this code
>>> compiles:
>>>
>>> try { }
>>> catch (Exception e) { ... }
>>>
>>> while the following does not compile:
>>>
>>> try { }
>>> catch (IOException e) { ... } //error IOException never thrown
>>
>> Thanks Maurizio. I never realized the above case existed. :)
>>
>> David
>> -----
>>
>>
>>>
>>> The code generating the newly added javac warnings will be changed
>>> accordingly; for example, the following will compile w/o warnings:
>>>
>>> try { throw new FileNotFoundException(); }
>>> catch (FileNotFoundException fnf) { ... }
>>> catch (Exception e) { ... }
>>>
>>> while the following code will still emit a 'dead catch' warning:
>>>
>>> try { throw new FileNotFoundException(); }
>>> catch (FileNotFoundException fnf) { ... }
>>> catch (IOException e) { ... }
>>>
>>>
>>> This should accommodate all weird cases of checked exceptions not being
>>> declared (as in Class.newInstance).
>>>
>>> Maurizio
>>>
>>>
>>>
>>>
>>>
>



More information about the core-libs-dev mailing list