2009-06-30 16 views
62

आमतौर पर Object.hashCode() का डिफ़ॉल्ट कार्यान्वयन स्मृति में ऑब्जेक्ट के आवंटित पते का कुछ कार्य है (हालांकि यह जेएलएस द्वारा अनिवार्य नहीं है)। यह देखते हुए कि वीएम स्मृति में स्मृति के बारे में बताता है, System.identityHashCode() द्वारा वापस मूल्य क्यों ऑब्जेक्ट के जीवनकाल में कभी नहीं बदला जाता है?JVM कैसे सुनिश्चित करता है कि System.identityHashCode() कभी नहीं बदलेगा?

यदि यह "एक-शॉट" गणना है (ऑब्जेक्ट की hashCode की गणना एक बार की जाती है और ऑब्जेक्ट हेडर या कुछ में छीन ली जाती है), तो इसका मतलब यह है कि दो ऑब्जेक्ट्स के लिए यह संभव है identityHashCode (यदि वे होते हैं स्मृति में एक ही पते पर पहली बार आवंटित किया जाएगा)?

+1

संबंधित प्रश्न: क्या यह स्मृति एक वास्तविक स्मृति पता या कुछ आभासी पता है जो ऑब्जेक्ट को शफल होने के बावजूद तय किया जा सकता है?यदि आभासी है, तो यह अच्छा होगा क्योंकि इसके लिए पॉइंटर्स को समायोजित करने की आवश्यकता नहीं होगी। दूसरी ओर, इसका मतलब एक अतिरिक्त संकेत और संभावित रूप से बड़ी मैपिंग तालिका होगी। – Thilo

+3

पहली बार अनुरोध किए जाने पर पते का मामूली पुनर्गठन है। (कम बिट्स के साथ एक हैश कोड लौटने से सभी शून्य बहुत अच्छा नहीं है।) –

+0

दरअसल, यह कहां कहता है कि पहचान हैशकोड कभी नहीं बदला जाना चाहिए? System.identityHashCode के लिए JavaDoc उस पर स्पष्ट नहीं है। – Thilo

उत्तर

35

आधुनिक जेवीएम ऑब्जेक्ट हेडर में मान को सहेजते हैं। मेरा मानना ​​है कि मान आमतौर पर ऑब्जेक्ट आवंटन में कम से कम समय (कभी-कभी कम से कम एक दर्जन चक्र के रूप में कम) रखने के लिए पहले उपयोग पर गणना की जाती है। सामान्य सूर्य जेवीएम संकलित किया जा सकता है ताकि सभी वस्तुओं के लिए पहचान हैश कोड हमेशा 1 हो।

एकाधिक ऑब्जेक्ट्स में एक ही पहचान हैश कोड हो सकता है। यह हैश कोड की प्रकृति है।

+3

दाएं - मैंने ऑब्जेक्ट सिंक्रनाइज़र :: FastHashCode के माध्यम से synchronizer.cpp (vm रनटाइम स्रोत कोड) में और हैशकोड उत्पन्न करने के बाद देखा है, ऐसा लगता है कि यह ऑब्जेक्ट हेडर में विलीन हो जाता है। ऐसा लगता है कि हैशकोड के कई संभावित कार्यान्वयन हैं; जिस वस्तु का आप सभी ऑब्जेक्ट्स के लिए 1 लौटते हैं, यह सुनिश्चित करने के लिए प्रयोग किया जाता है कि वीएम का कोई भी हिस्सा हैशकोड किसी भी कारण से अद्वितीय नहीं है। – butterchicken

+0

सार्वजनिक स्थैतिक देशी int पहचान हैशकोड (ऑब्जेक्ट एक्स); एक मूल विधि है। क्या आप इसे मूल कार्यान्वित कोड परिप्रेक्ष्य से समझा सकते हैं? मेरा मतलब है कि सी ++ कार्यान्वयन.आईटी मुख्य रूप से इडेंटिटी हैश मैप में उपयोग किया जाता है? –

+0

@Tom ऑब्जेक्ट हेडर द्वारा आपका क्या मतलब है? आपने यह भी लिखा है "मुझे विश्वास है कि मूल्य आमतौर पर ऑब्जेक्ट आवंटन को कम से कम रखने के लिए पहले उपयोग पर गणना की जाती है (कभी-कभी कम से कम एक दर्जन चक्र के रूप में)।" क्या आप समझा सकते हैं कि आप किस ऑब्जेक्ट आवंटन का जिक्र कर रहे हैं? – Geek

-3

जहां तक ​​मुझे पता है, यह संदर्भ वापस करने के लिए लागू किया गया है, जो किसी ऑब्जेक्ट जीवनकाल में कभी नहीं बदलेगा।

+0

तो आप कह रहे हैं कि संदर्भ वास्तविक स्मृति पता नहीं है (या उससे सीधे प्राप्त किया गया है)। तो क्या यह वास्तविक स्मृति पते के लिए एक सूचक है? – Thilo

15

दूसरे प्रश्न के उत्तर में, कार्यान्वयन के बावजूद, एकाधिक ऑब्जेक्ट्स के लिए एक ही पहचान हैशकोड होना संभव है।

जावाडोक में शब्दों पर एक संक्षिप्त चर्चा के लिए bug 6321873 देखें, और एक विशिष्टता को प्रदर्शित करने के लिए एक कार्यक्रम देखें।

+1

सच है। दो अलग-अलग ऑब्जेक्ट्स में एक ही हैशकोड हो सकता है। यही हैश सभी कार्यों के साथ है (एक डोमेन पर उनके परिणाम के आकार के बाद बड़ा)। – Thilo

+2

यह एक बहुत अच्छी बग रिपोर्ट है कि। :) –

+1

@ थिलो: जेवीएम इस तरह के फैशन में यह गारंटी देने के लिए लिखा जा सकता था कि बशर्ते कि एक बार में अस्तित्व में चार अरब से अधिक वस्तुएं न हों, 'पहचान हैशकोड' कभी भी एक मूल्य वापस नहीं लौटाएगा जो किसी अन्य के साथ लौटा दिया गया था ऑब्जेक्ट जो अभी भी अस्तित्व में है। मेमोरी मैनेजर को कैसे कार्यान्वित किया जाता है, इस पर निर्भर करता है, यह महंगा हो सकता है, या यह शून्य अतिरिक्त लागत जोड़ सकता है। उदाहरण के लिए, 'ऑब्जेक्ट' में पॉइंटर्स की एक तालिका में एक इंडेक्स हो सकता है, प्रत्येक ऑब्जेक्ट को तब तक तालिका स्लॉट असाइन किया जा सकता है जब तक यह मौजूद हो। विशिष्ट जेवीएम कार्यान्वयन ऐसा नहीं करते हैं ... – supercat

0

एक हैशिंग समारोह को लागू करने के लिए सामान्य दिशानिर्देश है:

  • एक ही वस्तु के लिए एक सुसंगत hashCode लौट जाना चाहिए, यह (समय के साथ बदलने के लिए या निर्भर नहीं रहना चाहिए किसी भी चर सूचना के आधार पर जैसे एक एल्गोरिथ्म एक से वरीयता प्राप्त यादृच्छिक संख्या या परिवर्तनशील सदस्य फ़ील्ड के मानों का
  • हैश फंक्शन एक अच्छा यादृच्छिक वितरण होना चाहिए, और उस से मेरा मतलब है अगर आप बाल्टी के रूप में hashCode पर विचार, 2 वस्तुओं के रूप में जहाँ तक संभव हो विभिन्न बाल्टी (hashcodes) करने के लिए नक्शे चाहिए संभावना है कि 2 वस्तुओं एक ही हैशकोड दुर्लभ होना चाहिए - हालांकि यह हो सकता है।
0

हॉटस्पॉट में किसी ऑब्जेक्ट के शीर्षलेख में क्लास पॉइंटर और "मार्क" शब्द होता है।

मार्क शब्द के लिए डेटा संरचना का स्रोत कोड markOop.hpp फ़ाइल पाया जा सकता है। फ़ाइल में एक टिप्पणी का वर्णन निशान शब्द की स्मृति लेआउट है:

hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

यहाँ हम देख सकते हैं कि सामान्य जावा के लिए पहचान हैश कोड एक 32 बिट सिस्टम पर वस्तुओं में सहेजा जाता है शब्द चिह्नित करें और यह 25 बिट लंबा है।