Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.7.10, 1.8-rc-3, 1.9-beta-1
-
None
Description
Not normally a piece of code I would write, but a post in stackoverflow.com brought to my attention this bug.
I don't know the exact trigger, but it seems that a nested try block, with an explicit return on one of the finally clauses, when written as the final statement of a function is throwing a NullPointerException at groovyjarjarasm.asm.MethodWriter#visitMaxs
This script is the shortest example I got.
try { try {} finally {} } finally { return 0 }
Things to note:
It's the last statement of the script's run()
There is a nested try block. The blocks could be a try/catch, try/finally or try/catch/finally blocks with identical behavior
The explicit return could be anything, it will fail to compile.
There cannot be anything between the finally clauses and the end of the function.
a little bit longer
try { // 1 try { // 2 } finally { // 3 return -1 // 4 } // 5 } finally { // 6 return -2 // 7 } //8
There can be anything in positions 1-4,6,7
The script can be compiled when there is a statement in positions 5 or 8
Either of the explicit returns is enough, not necessarily both.
The full stacktrace is
Caught: java.lang.NullPointerException java.lang.NullPointerException at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source) at org.objectweb.asm.MethodAdapter.visitMaxs(Unknown Source) at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:595) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:123) at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:686) at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1039) at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:50) at org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:276) at org.codehaus.groovy.control.CompilationUnit$12.call(CompilationUnit.java:748) at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:942) at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:519) at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:497) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:474) at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:306) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:283) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:267) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:197) at groovy.lang.GroovyShell$2.run(GroovyShell.java:215) at groovy.lang.GroovyShell$2.run(GroovyShell.java:213) at java.security.AccessController.doPrivileged(Native Method) at groovy.lang.GroovyShell.run(GroovyShell.java:213) at groovy.lang.GroovyShell.run(GroovyShell.java:159) at groovy.ui.GroovyMain.processOnce(GroovyMain.java:496) at groovy.ui.GroovyMain.run(GroovyMain.java:311) at groovy.ui.GroovyMain.process(GroovyMain.java:297) at groovy.ui.GroovyMain.processArgs(GroovyMain.java:112) at groovy.ui.GroovyMain.main(GroovyMain.java:93) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:108) at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:130)