2017-07-03 2 views
3

Wenn ich mit einem vorhandenen Code arbeite, habe ich ein Problem während der Laufzeit bei der Ausführung des Codes mit Eclipse Neon.3. Leider war ich nicht in der Lage, die Ausnahme in einem minimalen Arbeitsbeispiel zu reproduzieren, sondern die folgende Ausgabe vom Classloader hergestellt:Eclipse: "Unbekannter Fehler" während Typinterferenz

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack 
Exception Details: 
    Location: 
    ... 
    Reason: 
    Type 'java/lang/Object' (current frame, stack[8]) is not assignable to 'MyMap' 
    Current Frame: 
    ... 
    Bytecode: 
    ... 
    Stackmap Table: 
    ... 

Es funktioniert auf der Kommandozeile und in älteren Versionen Eclipse, so dass es keine Rolle viel zu dieser Zeit. Letzte Woche, Eclipse Oxygen.1 wurde veröffentlicht und wir begannen damit. Nun erzeugt der gleiche Code eine Compiler-Ausnahme:

Problem detected during type inference: Unknown error at invocation of reduce(Main.MyMap<MyKey,MyValue>, BiFunction<Main.MyMap<MyKey,MyValue>,? super MyValue,Main.MyMap<MyKey,MyValue>>, BinaryOperator<Main.MyMap<MyKey,MyValue>>) 

Ich habe es geschaffen, ein minimales Arbeitsbeispiel zusammen zu stellen, die diesen Fehler in Eclipse erzeugt, sondern arbeiten auf der Kommandozeile:

import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Set; 

public class Main<MyKey, MyValue> { 

    static class MyMap<K, V> extends HashMap<K, V> { 
     public MyMap<K, V> putAllReturning(MyMap<K, V> c) { putAll(c); return this; } 
     public MyMap<K, V> putReturning(K key, V value) { put(key, value); return this; } 
    } 

    public Main() { 
     Set<MyValue> values = new HashSet<>(); // actually something better 
     final MyMap<MyKey, MyValue> myMap = 
       values.stream() 
        .reduce(
         new MyMap<MyKey, MyValue>(), 
         (map, value) -> { 
          Set<MyKey> keys = new HashSet<>(); // actually something better 

          return keys.stream() 
           .reduce(
            map, // this would work syntactically: new MyMap<MyKey, MyValue>(), 
            (map2, key) -> map2.putReturning(key, value), 
            MyMap::putAllReturning); 
         }, 
         MyMap::putAllReturning 
        ); 
    } 
} 

Es Es scheint, dass der erste Parameter für das innere Reduzieren eine Unterbrechung der Typinferenz verursacht, da das Ersetzen durch eine andere Instanz desselben Typs (aber explizit deklariert anstatt abgeleitet) den Fehler beseitigt.

Die genaue Quelle des Fehlers in der Klasse zu kennen, erlaubte uns, den Code neu zu schreiben (den Lambda-Ausdruck zu extrahieren, der an das äußere reduziert wurde, auf seine eigene Methode zu reduzieren). Allerdings wäre ich immer noch an einer Erklärung interessiert, warum solch ein Konstrukt die beiden neueren Eclipse-Compiler kaputt machen könnte.

+1

Neben der Eclipse-Ausgabe OK kompiliert, wird dieser Code sowieso gebrochen. Sie sollten den Unterschied zwischen [Reduktion] (https://docs.oracle.com/javase/patage-summary.html#Reduction) und [Veränderliche Reduktion] (https: //docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction) oder die Bedeutung des [identity value] (https://stackoverflow.com/a/ 32867283/2711488), als erstes Argument von ['reduce'] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-U-java. util.function.BiFunction-java.util.function.BinaryOperator-) ... – Holger

+0

Danke für das Beispiel, siehe https://bugs.eclipse.org/519147 –

+1

Es stellt sich heraus, dass das Problem in der ECJ-Emulation von Javacs seit langem bestehender Bug verursacht wurde https://bugs.openjdk.java.net/browse/JDK-8026527 - aus naheliegenden Gründen gibt es keine genaue Spezifikation dafür. Behoben für Photon M5. –

Antwort

3

gut für mich auf Oxygen, es funktionierte einfach für die Parameter erklärt, die reduzieren:

(MyMap<MyKey, MyValue> map, MyValue value) -> .... 

die genaue Problem und warum Eclipse Compiler wissen, können die Arten nicht ableiten zu viel für mich ist; In beiden Fällen sollte dies gemeldet werden (dies könnte dem Eclipse-Team bereits bekannt sein).

Ich kann auch bestätigen, dass es mit jdk-8-131 und jdk-9-175

+0

Danke für die Eingabe. Dies scheint die am wenigsten invasive Änderung zu sein, um alle relevanten Compiler zu unterstützen. –

Verwandte Themen