[讨论] 关于try-finally编译

miroku 2013-06-21
最近在看JLS中关于try-cache-finally的编译,有一些问题不明白,请各位大神指点,代码如下:
public class TestReturn {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TestReturn obj = new TestReturn();
		System.out.println(obj.get());
	}
	
	public String get(){
		String ret = "";
		try{
			ret = "aa";
			return ret;
		}finally{
			ret = "bb";
		}
	}

}

javac后的字节码如下,只贴出了get()方法的
 public java.lang.String get();
   flags: ACC_PUBLIC
   Code:
     stack=1, locals=4, args_size=1
        0: ldc           #36                 // String aa
        2: astore_1
        3: aload_1
        4: astore_3
        5: ldc           #38                 // String bb
        7: astore_1
        8: aload_3
        9: areturn
       10: astore_2
       11: ldc           #38                 // String bb
       13: astore_1
       14: aload_2
       15: athrow
     Exception table:
        from    to  target type
            3     5    10   any
     LineNumberTable:
       line 14: 0
       line 16: 3
       line 18: 5
       line 16: 8
       line 17: 10
       line 18: 11
       line 20: 14
     LocalVariableTable:
       Start  Length  Slot  Name   Signature
              0      16     0  this   Lcpm/soso/quan/TestReturn;
              3      13     1   ret   Ljava/lang/String;
     StackMapTable: number_of_entries = 1
          frame_type = 255 /* full_frame */
         offset_delta = 10
         locals = [ class cpm/soso/quan/TestReturn, class java/lang/String ]
         stack = [ class java/lang/Throwable ]


这里有几个疑问:
1、首先上面代码打印的是  aa
2、编译后第4行字节码多了我java代码没有定义的局部变量,java代码中只有2个,但是编译后却有4个

请各位大神指点
RednaxelaFX 2013-06-21
直接在finally里用return语句可以干涉返回值,但只是改变显式的局部变量则不改变返回值。finally在执行时,语义上说那个try块里的return语句已经执行完了,只是控制流临返回之前进入finally块里转一圈而已。因而这个例子在实际javac实现中,try块里的return语句要返回的值被缓存在了一个编译器生成的局部变量里(slot 3),等实际返回的时候再拿出来。

slot 2则被用于临时存放try块里可能抛出的异常,用于在finally末尾重新抛出。
miroku 2013-06-22
RednaxelaFX 写道
直接在finally里用return语句可以干涉返回值,但只是改变显式的局部变量则不改变返回值。finally在执行时,语义上说那个try块里的return语句已经执行完了,只是控制流临返回之前进入finally块里转一圈而已。因而这个例子在实际javac实现中,try块里的return语句要返回的值被缓存在了一个编译器生成的局部变量里(slot 3),等实际返回的时候再拿出来。

slot 2则被用于临时存放try块里可能抛出的异常,用于在finally末尾重新抛出。


这个是JLS要求的么?我在JLS7里没看到相应的说明,还是说这个只是hotspot的一个实现?
RednaxelaFX 2013-06-22
miroku 写道
RednaxelaFX 写道
[color=red]直接在finally里用return语句可以干涉返回值,但只是改变显式的局部变量则不改变返回值。finally在执行时,语义上说那个try块里的return语句已经执行完了,只是控制流临返回之前进入finally块里转一圈而已。[/url]因而这个例子在实际javac实现中,try块里的return语句要返回的值被缓存在了一个编译器生成的局部变量里(slot 3),等实际返回的时候再拿出来。

slot 2则被用于临时存放try块里可能抛出的异常,用于在finally末尾重新抛出。


这个是JLS要求的么?我在JLS7里没看到相应的说明,还是说这个只是hotspot的一个实现?

标红的地方是JLS规定的,其它是Oracle/Sun JDK里的javac的实现细节。跟HotSpot VM没关系。
Global site tag (gtag.js) - Google Analytics