2014-09-13 16 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(); 
    }       
} 

Dlaczego ten program wyświetla "źle"? Jeśli usunę Lambdę, lub jeśli podzielę klauzulę wielopozycyjną, to wydrukuje "prawo".Błąd Java podczas łączenia lambdas i klauzul multi-catch?

$ 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) 

Odpowiedz

11

To był fixed bug w 1.8.0_20, od 1.8.0_11:

Area: Narzędzia/javac
Synopsis: javac generuje nieprawidłowe tabeli wyjątku dla sprawozdania multi-połowowych wewnątrz lambda

Poprawiono obsługę próbnego połowu z wieloma chwytami wewnątrz lambda.

Rzeczywista raport o błędzie jest JDK-8036942

Co faktycznie poszło był domniemany typ utraty informacji w kompilatora:

LTM sprawia, że ​​ciężkie użycia skasowaniem() podczas tłumaczeń i odwzorowania zmienne. Operacje usuwania mogą być w większości przypadków poprawne, ale może to prowadzić do utraty informacji, jak pokazuje ten przypadek. Jest też zapewne takie intensywne użycie funkcji wymazywania(), ponieważ LTM jest stosowany po TransTypes, który ma usunąć większość/wszystkie typy, więc zastanawiam się, czy to może być błąd w TransTypes. Sądzę, że powinien on zostać oceniony przez Roberta Fielda, który jest aktualnym opiekunem LTM, co jest najlepszym podejściem, tym samym przekazuję mu je [sic].

Co widzę na 8u20 (zapomniałem podać parametr wiersza poleceń i nie mają już 8u20 zrobić to poprawnie):

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% 

Poprawnie:

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

Ten problem został rozwiązany z 1.8.0_20 https://bugs.openjdk.java.net/browse/JDK-8036942

jestem w stanie replikować go 1.8.0_11 i jest mocowana za pomocą 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 

działa poprawnie

~$ 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 
Powiązane problemy