2015-10-05 7 views
8

को लक्षित करना मैं आज एक बहुत ही अनपेक्षित त्रुटि में भाग गया और जब तक मैं पूरी तरह से समस्या को ठीक करने का कोई तरीका नहीं ढूंढ पाया, मुझे यकीन नहीं है कि मैं पूरी तरह समझता हूं कि ऐसा क्यों हुआ यह किया।जेडके 8 के साथ संकलित समवर्ती हैश मैप क्रैशिंग एप्लिकेशन लेकिन जेआरई 7

जिस कोड के साथ मैं काम कर रहा हूं वह मूल रूप से जेडीई 7 के लक्ष्यीकरण के जेडीके 7 पर्यावरण के साथ लिखा गया था। कोड में मैं ConcurrentHashMap का उपयोग कर रहा था और मानचित्र में चाबियों को फिर से चलाने की आवश्यकता थी। इसके लिए मैं map.keySet() का उपयोग कर रहा था जो जावाडॉक्स के अनुसार Set<K> लौटा देना चाहिए। यह तब तक ठीक काम करता जब तक कि हमारे निर्माण पर्यावरण ने जेडीके 8 पर स्विच नहीं किया।

जब हम जेडीके 8 में चले गए तो मैंने सुनिश्चित किया कि मैं जावैक को कॉल करते समय 1.7 के लिए लक्ष्य/स्रोत कह रहा था। इसलिए जब मैं मानचित्र की चाबियों के माध्यम से पुन: प्रयास करना चाहता था तो कोड बहुत असफल रहा जब मैं बहुत आश्चर्यचकित था। कोई त्रुटि नहीं फेंक दी गई, कोई अपवाद नहीं, धागा बस बंद कर दिया। कुछ शोध करने के बाद मैंने पाया कि ConcurrentHashMap.keySet() विधि के लिए Java8 का कार्यान्वयन KeySetView<K,V> देता है।

मैंने का उपयोग map.keys() का उपयोग करके Enumeration<K> प्राप्त करने से स्विच करके समस्या को ठीक किया।

अब मेरी समस्या यह है कि यद्यपि परियोजना को जावा 7 को लक्षित करने के लिए संकलित किया गया था क्योंकि जेडीके 8 का इस्तेमाल जावा 8 पुस्तकालयों में किया गया था, लेकिन जब यह मेल नहीं खाता तो यह त्रुटि या अपवाद क्यों नहीं फेंक दिया?

के रूप में यहां से पूछा एक कोड का टुकड़ा है:

class MapProcessing 
{ 
    private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>(); 

    public MapProcessing() 
    { 
      map.put("First",new Object()); 
      map.put("Second",new Object()); 
      map.put("Third",new Object()); 
    } 


    public void processing() 
    { 
      // when calling this type of loop causes a freeze on our system. 
      for(String key : map.keySet()) 
      { 
       System.out.println(key); 
      } 
     } 

    public void working() 
    { 
     // This is what I had to do to fix the problem. 
     Enumeration<String> keys = map.keys(); 
     while(keys.hasMoreElements()) 
     { 
       String key = keys.nextElement(); 
       System.out.println(key); 
     } 
    } 
} 

हम ओरेकल JDK 8 निर्माण 40 का उपयोग कर एक Windows 2012 सर्वर पर 1.7 के लिए एक लक्ष्य और javac में स्रोत 1.7 का उपयोग कर संकलन कर रहे हैं।

यह कोड विंडोज 2012 सर्वर पर चल रहे ओरेकल जेवीएम 7 बिल्ड 25 का उपयोग कर चल रहा है।

+0

क्या आपने जेडीके 8 को जोड़ने के बाद इसे साफ करने का प्रयास किया? –

+0

@ सुरेश बिल्ड बिल्डिंग एक जेनकींस है। जब हम जेडीके 8 में चले गए तो हमने वर्कस्पेस हटा दिया और फिर एक नया निर्माण किया। इसका मतलब यह होगा कि कोड को एसवीएन से ताजा चेक किया गया था और फिर बनाया गया था। मुझे यकीन नहीं है कि मानक कॉल के अलावा चींटी को "साफ" लक्ष्य में एंटी में छोड़कर इसका मतलब क्या है, जो होता है। – JRSofty

+0

क्या आप एक कोड स्निपेट और सटीक जेवीएम संस्करण और विक्रेता + ओएस पोस्ट कर सकते हैं? KeySetView लागू लागू करें, इसलिए कम से कम यह वास्तव में एक समस्या नहीं होनी चाहिए – salyh

उत्तर

12

तो मैं जावा 8 के साथ अपने कोड और javac स्रोत 1.7 -target 1.8 और उसके बाद जावा 7 के साथ इसे चलाने के संकलन मैं प्राप्त एक

 
Exception in thread "main" java.lang.NoSuchMethodError: 
    java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; 
    at stackoverflowt.Test.processing(Test.java:20) 
    at stackoverflowt.Test.main(Test.java:27) 

इसका कारण यह है बाइट कोड

 
public void processing(); 
    Code: 
     0: aload_0  
     1: getfield  #4     // Field map:Ljava/util/concurrent/ConcurrentHashMap; 
     4: invokevirtual #10     // Method java/util/concurrent/ConcurrentHashMap.keySet:()Ljava/util/concurrent/ConcurrentHashMap$KeySetView; 
     7: invokevirtual #11     // Method java/util/concurrent/ConcurrentHashMap$KeySetView.iterator:()Ljava/util/Iterator; 
     10: astore_1  
की तरह लग रहा है

और स्पष्ट रूप से ConcurrentHashMap $ KeySetView को संदर्भित करता है जो जावा 7 में मौजूद नहीं है। मैं जावा 1.7.0_79 और 1.8 के साथ मैक पर हूं।0_45

आप के लिए (केवल मानचित्र इंटरफ़ेस का उपयोग करें) कोड को बदलते हैं:

private Map<String, Object> map = new ConcurrentHashMap<String, Object>(); 

तो यह मेरे लिए काम। बाइटकोड तब

 
public void processing(); 
    Code: 
     0: aload_0  
     1: getfield  #4     // Field map:Ljava/util/Map; 
     4: invokeinterface #10, 1   // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set; 
     9: invokeinterface #11, 1   // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator; 
     14: astore_1  
+1

दिलचस्प। मैंने सामान्य मानचित्र इंटरफ़ेस का उपयोग करने के बारे में सोचा नहीं था। अफसोस की बात है, मैंने कभी 'NoSuchMethodError' नहीं देखा। मैं कम से कम उम्मीद की थी। मुझे यह देखने के लिए कल फिर से कोड में देखना होगा कि त्रुटि प्रबंधन वास्तव में सबकुछ सही तरीके से पकड़ रहा है या नहीं। धन्यवाद। – JRSofty

+0

मैंने आज सुबह अपना कोड चेक किया और सुनिश्चित किया कि कॉल जो कुछ भी बंद कर देता है उसे पकड़ने की कोशिश में लपेटा जाता है लेकिन केवल अपवादों को पकड़ता है और 'NoSuchMethodError'' थ्रोबल 'है लेकिन' अपवाद 'नहीं है। इससे मुझे बेहतर समझ मिलती है कि प्रोग्राम को तोड़ने पर मुझे कोई त्रुटि क्यों नहीं मिली। – JRSofty

+0

@JRSofty अगर यह एक समस्या है कि जावा इससे पुनर्प्राप्त नहीं हो सकता है, तो यह एक ['त्रुटि'] होगा (https://docs.oracle.com/javase/8/docs/api/java/lang/Error .html), जो 'थ्रोबल' का उप-वर्ग है लेकिन 'अपवाद' नहीं है। – Powerlord

2

जब भी आप एक परियोजना -source तर्क एक पुराने संस्करण लक्ष्यीकरण का उपयोग कर एक नए JDK का उपयोग कर निर्माण, तो आप इस संकलक चेतावनी दी जाएगी:

warning: [options] bootstrap class path not set in conjunction with -source 1.7

This blog entry इसका क्या मतलब के बारे में बात करती है।

असल में, आपको यह चेतावनी मिलती है क्योंकि जावा पुराने भाषा नियमों का उपयोग करके इसे संकलित कर रहा है लेकिन नई कक्षा लाइब्रेरी के खिलाफ ... और जावा 8 संस्करणों के साथ कुछ संगतता समस्याएं हैं क्योंकि ओरेकल ने आंतरिक कक्षाओं में से कुछ को स्थानांतरित किया है।

फिक्सिंग -bootclasspath तर्क का उपयोग करने के लिए rt.jar पर संकलित करते समय इसे पुराने संस्करण से इंगित करने के लिए है।

+0

ठीक है, इसलिए '-bootclasspath' विकल्प का उपयोग कर सही rt.jar पर इशारा करते हुए जोड़ना अपेक्षित कार्य करना चाहिए। हालांकि मुझे लगता है कि मेरा फिक्स शायद बेहतर है क्योंकि इसका मतलब है कि जब हम जेआरई 8 चलाने वाली प्रणाली पर एप्लिकेशन को तैनात करते हैं तो मुझे इसके बारे में चिंता करने की ज़रूरत नहीं है। मैं इस बारे में उत्सुक हूं कि जब मैं प्रोग्राम चलाता हूं तो मुझे अपवाद या त्रुटि क्यों नहीं मिली? मेरे लिए धागा बस रुक गया और कोई अपवाद नहीं फेंक दिया गया। – JRSofty

+0

बिल्ड पर्यावरण पर जानकारी के लिए फिर से धन्यवाद। मैं जितनी जल्दी हो सके इसे ठीक कर दूंगा। हमने 'javac' चींटी कार्य में 'bootclasspath' विकल्प कभी नहीं जोड़ा। मैं तुरंत ऐसा करूँगा। – JRSofty

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