2013-09-29 11 views
7

एक आंतरिक वर्ग सिंक्रनाइज़ किया गया है - java.util.Collections के अंदर दो कन्स्ट्रक्टर के साथ। पहला संग्रह लेता है और दूसरा संग्रह और म्यूटेक्स लेता है। पूर्व कन्स्ट्रक्टर नल होने के लिए तर्क की जांच करता है। लेकिन बाद में नहीं! यहां कार्यान्वयन है।क्या यह जावा सिंक्रनाइज़ेशन चयन कक्षा में एक बग है?

SynchronizedCollection(Collection<E> c) { 
     if (c==null) 
      throw new NullPointerException(); 
     this.c = c; 
     mutex = this; 
    } 
SynchronizedCollection(Collection<E> c, Object mutex) { 
     this.c = c; 
     this.mutex = mutex; 
} 
इस कार्यान्वयन मैं कक्षा दूसरी निर्माता को अशक्त भेजकर अपरिवर्तनीय तोड़ सकते हैं साथ

मेरा मानना ​​है यह कुछ इस तरह होना चाहिए:

SynchronizedCollection(Collection<E> c) { 
     this(c,this) 
    } 
SynchronizedCollection(Collection<E> c, Object mutex) { 
     if (c==null) 
      throw new NullPointerException(); 
     this.c = c; 
     this.mutex = mutex; 
} 

लेकिन मैं अपने आप को समझाने नहीं कर सकते जोश बलोच और नील Gafter यह नहीं देख सकता था। तो क्या आप वास्तव में मुझे बता सकते हैं कि मैं यहां क्या चूक गया?


संपादित: संभावित हमले

Map<String, String> m = new Map<String, String>(){ 

     @Override 
     public int size() { 
      // TODO Auto-generated method stub 
      return 0; 
     } 

        . 
        . 
        . 

     @Override 
     public Collection<String> values() { 
      return null; 
     } 


    }; 

    Map<String, String> synchronizedMap = Collections.synchronizedMap(m); 
    Collection<String> values = synchronizedMap.values(); 

उत्तर

11

निश्चित रूप से यह एक बग है। दोनों रचनाकारों को सुसंगत होना चाहिए, दोनों को अपवाद फेंकना चाहिए या किसी को भी फेंकना चाहिए।

यह जावा 8. में तय किया गया है अब दोनों कंस्ट्रक्टर्स अपवाद फेंक देगा:

SynchronizedCollection(Collection<E> c) { 
    this.c = Objects.requireNonNull(c); 
    mutex = this; 
} 

SynchronizedCollection(Collection<E> c, Object mutex) { 
    this.c = Objects.requireNonNull(c); 
    this.mutex = Objects.requireNonNull(mutex); 
} 
2
उन निर्माताओं की

दोनों पैकेज की रक्षा की और केवल पहले से एक हैं संभवतः Collections की publicsynchronizedList() और synchronizedSet() तरीकों के माध्यम से एक null तर्क के साथ प्रयोग किया जा सकता है।

अन्य कन्स्ट्रक्टर आंतरिक रूप से उपयोग किया जाता है (Collections वर्ग में) और पहला तर्क विभिन्न कार्यान्वयन (कॉलिंग कोड) में null कभी नहीं हो सकता है ताकि आप इसे तोड़ सकें।

आप हमेशा java.util पैकेज में कुछ बनाने का प्रयास कर सकते हैं लेकिन आपको अधिकतर SecurityException मिल जाएगा।

+2

मैं मानचित्र इंटरफ़ेस फैली एक ओवरराइड मूल्यों() विधि java.util पैकेज में मेरी कार्यान्वयन डाले बिना अशक्त वापस जाने के लिए! मूल्य() विधि द्वारा ऑब्जेक्ट रिटर्न दूसरे कन्स्ट्रक्टर को भेजता है - संग्रह। सिंक्रनाइज़मैप() और बूम देखें !! –

+0

मेरा संपादन नोट देखें –

+1

@MortezaAdi उचित होने के लिए, जिसे 'Map.values ​​()' के अनुबंध का दुरुपयोग करने के रूप में तर्क दिया जा सकता है जो उस व्यवहार को स्पष्ट रूप से अनुमति नहीं देता है। (यह इसे या तो अस्वीकार नहीं करता है, लेकिन: क्या आप ** ** प्रविष्टिसेट() ',' keySet() 'या' मान() 'से वापसी मानों को निरस्त करते हैं? क्या आपने कभी किसी और को देखा है तो?) मैं आपको दूंगा कि कक्षा में मजबूती की कमी है लेकिन वास्तव में एपीआई का दुरुपयोग किए बिना इसे तोड़ने का कोई तरीका नहीं है। मैं सोटिरियोस से सहमत हूं कि अगर आप किसी तीसरे पक्ष के कोड में ब्रेकेज का कारण बन सकते हैं तो यह एक और मुद्दा होगा। – millimoose

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