2012-11-04 14 views
12

नीचे दिए गए कोड को चलाने से त्रुटि संदेश Bad type on operand stack में परिणाम मिलता है।ऑपरेंड स्टैक पर खराब प्रकार ... जेडीके 8 का उपयोग करके, अनाम आंतरिक कक्षाओं के साथ लैम्ब्डा विफल रहता है, क्यों?

public static void main(String args[]) { 
     TransformService transformService = (inputs) -> { 
      return new ArrayList<String>(3) {{ 
       add("one"); 
       add("two"); 
       add("three"); 
      }}; 
     }; 

     Collection<Integer> inputs = new HashSet<Integer>(2) {{ 
      add(5); 
      add(7); 
     }}; 
     Collection<String> results = transformService.transform(inputs); 
     System.out.println(results.size()); 
    } 

    public interface TransformService { 
     Collection<String> transform(Collection<Integer> inputs); 
    } 

हालांकि लैम्डा के भीतर डबल ब्रेस प्रारंभिक (अनाम आंतरिक कक्षाएं) को हटाने से कोड को उम्मीद के अनुसार चलाने की अनुमति मिलती है, क्यों? नीचे दिए गए काम:

public class SecondLambda { 
    public static void main(String args[]) { 
     TransformService transformService = (inputs) -> { 
      Collection<String> results = new ArrayList<String>(3); 
      results.add("one"); 
      results.add("two"); 
      results.add("three"); 

      return results; 
     }; 

     Collection<Integer> inputs = new HashSet<Integer>(2) {{ 
      add(5); 
      add(7); 
     }}; 
     Collection<String> results = transformService.transform(inputs); 
     System.out.println(results.size()); 
    } 

    public interface TransformService { 
     Collection<String> transform(Collection<Integer> inputs); 
    } 
} 

कंपाइलर बग? यह जल्दी पहुँच संस्करण सब के बाद ...

(यह संकलन नहीं होगा जब तक आप नवीनतम jdk 8 lambda download की है।)

+0

टैग लैम्ब्डा जावा के अलावा अन्य भाषाओं के लिए सी #, सी ++ जैसी भाषाओं के लिए है। – Lion

+8

@Lion: मेरा मानना ​​है कि जावा 8 लैम्बडा लागू करता है (मैंने कभी इसका उपयोग नहीं किया है, इसलिए मुझे यह तथ्य नहीं पता है), और इसलिए यह टैग प्रश्न के लिए उपयुक्त प्रतीत होता है। –

+11

@Lion यही कारण है कि जावा के पहले लैम्बडा नहीं था। एक लैम्ब्डा एक लैम्ब्डा है, भले ही यह भाषा के अल्फा संस्करण में हो। –

उत्तर

7

ऐसा लगता है कि समस्या तब होती है जब lambdaanonymous प्रकार देता है, लेकिन भले ही कोई अज्ञात वर्ग lambda के अंदर बनाया गया हो। यानी .:

public class TestLambda { 
    public static void main(String[] args) { 
     xxx(); 
    } 
    static void xxx() { 
     Functional1 f =() -> { 
      Object o = new Object() { }; 
      return new A(); 
     }; 
    } 
    static class A { } 
    static interface Functional1 { A func(); } 
} 

यह वास्तव में Exception in thread "main" java.lang.VerifyError: Bad local variable type (...) Reason: Type top (current frame, locals[0]) is not assignable to reference type की ओर जाता है।

आगे की जांच से पता चलता है कि अगर हम विधि xxx में पैरामीटर पेश करेंगे, तो अपवाद के कारण में इसका प्रकार होगा। उदा .:

Type 'java/lang/Integer' (current frame, stack[0]) is not assignable to 'lambda/TestLambda'

और यह पहले से ही बहुत ही दिलचस्प है। के शीर्ष वर्ग के टाइप करने के लिए, xxx पैरामीटर (जो वास्तव में नहीं किया जाता है) के प्रकार बदलने अर्थात TestLambda:

... 
    xxx(new TestLambda()); 
} 
private static void xxx(TestLambda x) { 
... 

और तुम क्या लगता है? यह समस्या को हल करता है! सब कुछ अच्छी तरह से काम शुरू करते हैं। यहां तक ​​कि, अगर हम return A(); से return new A() {}; बदल देंगे। इसे देखो!


मेरा निष्कर्ष है कि यह असली JVM बग है। ऐसा लगता है कि समस्या लोड कक्षाओं के ढेर के साथ है। यह विधि के साथ गठबंधन में होता है, जो Javalambda अभिव्यक्तियों (http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html) के अनुवाद के लिए उपयोग करता है - यह शीर्ष वर्ग के अंदर कृत्रिम तरीकों का उत्पादन करता है। ऐसा लगता है कि जब lambda में गुमनाम कक्षाएं पेश की जाती हैं तो ढेर टूट जाता है। यह उल्लिखित वर्कअराउंड का उपयोग करके तय किया जा सकता है।

2

संकलक बग है? यह सब होने के बाद जल्दी पहुँच संस्करण है ...

मैं कहूंगा कि किसी भी त्रुटि संदेश संकार्य ढेर उल्लेख अत्यधिक संभावना एक संकलक बग या JVM में एक बग के लिए एक कारण हो रहा है। विशेष रूप से यदि आप इसे शुद्ध जावा उदाहरण का उपयोग कर प्राप्त कर सकते हैं।

(ऐसा लगता है कि JVM एक typesafety समस्या यह है कि संकलक द्वारा खोजा गया है चाहिए सूचना दे रहा है, और/या वर्ग लोड समय में बाईटकोड सत्यापनकर्ता।) जावा 8 के लिए सिफारिश की चैनल के माध्यम से

रिपोर्ट यह कीड़े।

1

सीधे आपकी समस्या से संबंधित नहीं है, लेकिन मैं दृढ़ता से इस तरह से अज्ञात कक्षाओं का उपयोग न करने की अनुशंसा करता हूं। आप इसे दो मान जोड़ने के उद्देश्य से पूरी तरह से एक नया हैशसेट उपप्रकार बना रहे हैं। यह न केवल सिस्टम को उड़ाता है (यह हमेशा के लिए स्मृति में रहता है) यह जेवीएम के जेआईटी को भी परेशान कर सकता है क्योंकि यह कभी भी कॉल साइट पर हैशसेट को नहीं देखता है ... यह आपके द्वारा बनाए गए कई उपप्रकारों में से एक को देखता है।

संबंधित मुद्दे

 संबंधित मुद्दे