[
https://issues.apache.org/jira/browse/GROOVY-4721?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15889394#comment-15889394
]
Daniel Sun edited comment on GROOVY-4721 at 3/1/17 2:47 AM:
------------------------------------------------------------
{code}
String m() {
try {
String str = "hello";
return str;
} finally {
System.out.println("world");
}
}
{code}
Java will compile the above method into the following bytecode. As we can see,
local variable {{str}}'s range {{[L3, L2)}} covers {{L1}}, so the finally block
of nomal execution flow can access {{str}} on the bytecode level. I guess Java
control the access before generating bytecodes.
{code}
// access flags 0x0
m()Ljava/lang/String;
TRYCATCHBLOCK L0 L1 L2 null
L0
LINENUMBER 13 L0
LDC "hello"
ASTORE 1
L3
LINENUMBER 14 L3
ALOAD 1
ASTORE 2
L1
LINENUMBER 16 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "world"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L4
LINENUMBER 14 L4
ALOAD 2
ARETURN
L2
LINENUMBER 16 L2
FRAME SAME1 java/lang/Throwable
ASTORE 3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "world"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
ALOAD 3
ATHROW
L5
LOCALVARIABLE str Ljava/lang/String; L3 L2 1
LOCALVARIABLE this Lcom/groovyhelp/bytecodelab/TryCatchFinally; L0 L5 0
MAXSTACK = 2
MAXLOCALS = 4
{code}
was (Author: daniel_sun):
{code}
String m() {
try {
String str = "hello";
return str;
} finally {
System.out.println("world");
}
}
{code}
Java will compile the above method into the following bytecode. As we can see,
local variable {{str}}'s range {{ [L3, L2) }} covers {{L1}}, so the finally
block of nomal execution flow can access {{str}} on the bytecode level. I guess
Java control the access before generating bytecodes.
{code}
// access flags 0x0
m()Ljava/lang/String;
TRYCATCHBLOCK L0 L1 L2 null
L0
LINENUMBER 13 L0
LDC "hello"
ASTORE 1
L3
LINENUMBER 14 L3
ALOAD 1
ASTORE 2
L1
LINENUMBER 16 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "world"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L4
LINENUMBER 14 L4
ALOAD 2
ARETURN
L2
LINENUMBER 16 L2
FRAME SAME1 java/lang/Throwable
ASTORE 3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "world"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
ALOAD 3
ATHROW
L5
LOCALVARIABLE str Ljava/lang/String; L3 L2 1
LOCALVARIABLE this Lcom/groovyhelp/bytecodelab/TryCatchFinally; L0 L5 0
MAXSTACK = 2
MAXLOCALS = 4
{code}
> variable declared in try block is in scope in finally block
> -----------------------------------------------------------
>
> Key: GROOVY-4721
> URL: https://issues.apache.org/jira/browse/GROOVY-4721
> Project: Groovy
> Issue Type: Bug
> Components: Compiler
> Affects Versions: 2.4.0-rc-1
> Reporter: Hamlet D'Arcy
>
> This code should fail because 'x' is out of scope in the finally block.
> {code}
> class MyClass {
> def myMethod() {
> try {
> def x = 'foo'
> println x
> }
> finally {
> println x
> }
> }
> }
> new MyClass().myMethod()
> {code}
> Instead it prints 'foo' twice.
> if myMethod is static then it shows the behavior I expect.
> Could be something wrong with VariableScope somewhere?
> This example is from the Groovy codebase. We have code that relies on this
> behavior (although it is easy to find and fix, just run the UnusedVariable
> codenarc inspection, which is how I found it)
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)