groovy/groovy-core — pull request #139 by andresteingress (2013-02-11 22:19:30+00:00)
Title: GROOVY-5980: Finally executes twice on NPE while casting method result

Be aware that this fix patches the symptom only.

```groovy
int f() {
try { null } finally { println 'test' }
}
f()
```

causes the finally block to be executed two times. When having a look at the byte-code, you can see that loading and storing the const and unboxing it to an integer is indeed separated into two code blocks by the block recorder mechanism in StatementWriter#writeReturm/#writeTryCatchFinally.

In StatementWriter#writeReturn the finally block is embedded right after loading the first code block (loading and storing the null constant):

```
public int f();
flags: ACC_PUBLIC
Code:
stack=3, locals=4, args_size=1
0: invokestatic #20 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
3: astore_1
4: aconst_null
5: astore_2
6: nop
7: aload_1
8: ldc #74 // int 2
10: aaload
11: aload_0
12: ldc #76 // String test
14: invokeinterface #79, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
19: pop
20: nop
21: aload_2
22: invokestatic #85 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.intUnbox:(Ljava/lang/Object;)I
25: ireturn
26: goto
...
```

The problem is the DefaultTypeTransformation is failing to convert null to int. As a consequence, the catchAny block - filled with the finally statement code - is executed again.

```
6: goto 29
29: aload_1
30: ldc #86 // int 3
32: aaload
33: aload_0
34: ldc #76 // String test
36: invokeinterface #79, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
41: pop
42: nop
43: goto 62
46: astore_3
47: aload_1
48: ldc #87 // int 4
50: aaload
51: aload_0
52: ldc #76 // String test
54: invokeinterface #79, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
59: pop
60: aload_3
61: athrow
62: ldc #38 // int 0
64: ireturn
Exception table:
from to target type
4 7 46 any
21 29 46 any
LocalVariableTable:
Start Length Slot Name Signature
0 62 0 this Lbla;
LineNumberTable:
line 2: 4
```

This patch simply moves the type cast into the first block. If the cast fails, the catchAny block is executed and thus the finally code run only once.