2014-09-13 21 views
11
import java.io.*;    
import java.net.*;    

public class Test {   
    public static void main(String[] arguments) throws Exception { 
     Runnable runnable =() -> { 
      try { 
       throwException(); 
      } 
      catch (SocketException|EOFException exception) { 
       System.err.println("wrong"); 
      } 
      catch (IOException exception) { 
       System.err.println("right"); 
      } 
     }; 

     runnable.run(); 
    }       

    private static void throwException() throws IOException { 
     throw new NotSerializableException(); 
    }       
} 

這個程序爲什麼打印「錯誤」?如果我刪除了lambda,或者如果我拆分多catch子句,那麼它會打印「正確」。組合lambdas和multi-catch子句時出現Java錯誤?

$ javac -version 
javac 1.8.0_11 
$ java -version 
java version "1.8.0_11" 
Java(TM) SE Runtime Environment (build 1.8.0_11-b12) 
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode) 

回答

11

這是1.8.0_20一個fixed bug,從1.8.0_11:

:工具/ javac的
簡介:javac的生成不正確的異常表多catch語句拉姆達內

在lambda內處理多個捕獲的try-catch已得到糾正。

實際的錯誤報告是JDK-8036942

究竟是什麼出了問題是編譯器內的假定類型信息丟失:

LTM使得大量使用擦除(的)翻譯和映射過程變量。在大多數情況下,這些擦除操作可能是正確的,但這可能會導致信息丟失,如本例所示。這也可以說是在這裏需要如此強烈的使用擦除(),因爲在應該擦除大部分/所有類型的TransType之後應用LTM,所以我想知道這是否是TransTypes中的一個錯誤。我認爲應該由LTM的現任維護者羅伯特菲爾德來評估,這裏最好的方法是什麼,因此我將把它重新分配給他。

我對8u20看到什麼(我忘了給一個命令行參數,並且不再有8u20正確地做到這一點):

wlan1-loopback% /usr/lib/jvm/java-8-oracle/bin/javap -c Test 
Compiled from "Test.java" 
public class Test { 
    public Test(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]) throws java.lang.Exception; 
    Code: 
     0: invokedynamiC#2, 0    // InvokeDynamiC#0:run:()Ljava/lang/Runnable; 
     5: astore_1 
     6: aload_1 
     7: invokeinterface #3, 1   // InterfaceMethod java/lang/Runnable.run:()V 
     12: return 
} 
wlan1-loopback% java Test 
right 
wlan1-loopback% java -version 
java version "1.8.0_20" 
Java(TM) SE Runtime Environment (build 1.8.0_20-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) 
wlan1-loopback% 

正確:

public class Test { 
    public Test(); 
    descriptor:()V 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]) throws java.lang.Exception; 
    descriptor: ([Ljava/lang/String;)V 
    Code: 
     0: invokedynamiC#2, 0    // InvokeDynamiC#0:run:()Ljava/lang/Runnable; 
     5: astore_1 
     6: aload_1 
     7: invokeinterface #3, 1   // InterfaceMethod java/lang/Runnable.run:()V 
     12: return 

    private static void throwException() throws java.io.IOException; 
    descriptor:()V 
    Code: 
     0: new   #4     // class java/io/NotSerializableException 
     3: dup 
     4: invokespecial #5     // Method java/io/NotSerializableException."<init>":()V 
     7: athrow 

    private static void lambda$main$0(); 
    descriptor:()V 
    Code: 
     0: invokestatic #6     // Method throwException:()V 
     3: goto   27 
     6: astore_0 
     7: getstatic  #9     // Field java/lang/System.err:Ljava/io/PrintStream; 
     10: ldc   #10     // String wrong 
     12: invokevirtual #11     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     15: goto   27 
     18: astore_0 
     19: getstatic  #9     // Field java/lang/System.err:Ljava/io/PrintStream; 
     22: ldc   #13     // String right 
     24: invokevirtual #11     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     27: return 
    Exception table: 
     from to target type 
      0  3  6 Class java/net/SocketException 
      0  3  6 Class java/io/EOFException 
      0  3 18 Class java/io/IOException 
} 
10

此錯誤是固定的1.8.0_20 https://bugs.openjdk.java.net/browse/JDK-8036942

我能複製它1.8.0_11,它是固定的1.8.0_20

$ javac -version 
javac 1.8.0_11 
$ java -version 
java version "1.8.0_11" 
Java(TM) SE Runtime Environment (build 1.8.0_11-b12) 
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode) 
$ javac Test.java 
$ java Test 
wrong 

工作正常

~$ javac -version 
javac 1.8.0_20 
$ javac Test.java 
$ java -version 
java version "1.8.0_20" 
Java(TM) SE Runtime Environment (build 1.8.0_20-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) 
$ java Test 
right