दिलचस्प पोस्ट
रेल: फॉन्ट अद्भुत का उपयोग करना सी # – आर इंटरफ़ेस उपप्रोसेस: विंडोज में बाल प्रक्रियाएं हटाना क्यों एक आवेदन वर्ग का विस्तार? केवल एक वास्तविक रेखा पर मेरा विभाजित कार्य कैसे करें और स्ट्रिंग के उद्धृत भागों को छोड़ने में सक्षम हो? Foo और बार की उत्पत्ति क्या है? एससीएसएस में एक और वर्ग भी शामिल है "इस" मॉड्यूल का स्रोत कोड क्या कर रहा है? हैश तालिका / एसोसिएटिव ऐरे VBA में मैं अजगर में ऑब्जेक्ट का नाम कैसे प्राप्त करूं? मैं Gmail से अटैचमेंट्स के साथ सभी ईमेल कैसे डाउनलोड कर सकता हूं? अजगर के सुपरक्लाइड __इनिट_ विधि स्वचालित रूप से लागू क्यों नहीं हैं? जब मैं प्रोग्राममैटिक युग्मन कर रहा हूं, तो मैं एंड्रॉइड की ब्लूटूथ युग्मन अधिसूचना से कैसे बच सकता हूं या उसे कैद कर सकता हूं? क्या मैं एक पहचानकर्ता (एक तालिका या क्षेत्र का नाम) या एक वाक्य रचना कीवर्ड बाइंड करने के लिए एक पीडीओ तैयार कथन का उपयोग कर सकता हूं? पृष्ठ रीफ्रेश के बाद मूल्य को बनाए रखने के लिए जेएस वैरिएबल कैसे प्राप्त करें?

जावा में "आंतरिक पता" क्या है?

ऑब्जेक्ट के लिए जवाडॉक में हैशकोड () इसमें कहा गया है

यथोचित व्यावहारिक रूप से, कक्षा Object द्वारा परिभाषित हैश कोड विधि अलग-अलग ऑब्जेक्ट के लिए अलग-अलग पूर्णांक देता है। (यह आम तौर पर ऑब्जेक्ट के आंतरिक पते को एक पूर्णांक में परिवर्तित करके लागू किया जाता है, लेकिन यह कार्यान्वयन तकनीक जावा ™ प्रोग्रामिंग भाषा के द्वारा आवश्यक नहीं है।)

यह एक सामान्य माइक्रोनेशन है जिसमें मेमोरी एड्रेस के साथ ऐसा कुछ है, लेकिन ऐसा नहीं है कि बिना नोटिस के बदल सकते हैं और हैशोड () एक ऑब्जेक्ट के लिए नहीं बदलना चाहिए

@ नाइटी ने एक अच्छे उत्तर https://stackoverflow.com/a/565416/57695 के लिए एक लिंक प्रदान किया लेकिन मैं अधिक विवरणों की तलाश कर रहा हूं।


मेरी चिंता का वर्णन करने के लिए यहां एक उदाहरण है

 Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); for (int t = 0; t < 10; t++) { System.gc(); Object[] objects = new Object[10]; for (int i = 0; i < objects.length; i++) objects[i] = new Object(); for (int i = 0; i < objects.length; i++) { if (i > 0) System.out.print(", "); int location = unsafe.getInt(objects, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * i); System.out.printf("%08x: hc= %08x", location, objects[i].hashCode()); } System.out.println(); } 

प्रिंट

 eac00038: hc= 4f47e0ba, eac00048: hc= 2342d884, eac00058: hc= 7994d431, eac00068: hc= 19f71b53, eac00078: hc= 2e22f376, eac00088: hc= 789ddfa3, eac00098: hc= 44c58432, eac000a8: hc= 036a11e4, eac000b8: hc= 28bc917c, eac000c8: hc= 73f378c8 eac00038: hc= 30813486, eac00048: hc= 729f624a, eac00058: hc= 3dee2310, eac00068: hc= 5d400f33, eac00078: hc= 18a60d19, eac00088: hc= 3da5f0f3, eac00098: hc= 596e0123, eac000a8: hc= 450cceb3, eac000b8: hc= 4bd66d2f, eac000c8: hc= 6a9a4f8e eac00038: hc= 711dc088, eac00048: hc= 584b5abc, eac00058: hc= 3b3219ed, eac00068: hc= 564434f7, eac00078: hc= 17f17060, eac00088: hc= 6c08bae7, eac00098: hc= 3126cb1a, eac000a8: hc= 69e0312b, eac000b8: hc= 7dbc345a, eac000c8: hc= 4f114133 eac00038: hc= 50c8c3b8, eac00048: hc= 2ca98e77, eac00058: hc= 2fc83d89, eac00068: hc= 034005e1, eac00078: hc= 6041f871, eac00088: hc= 0b1df416, eac00098: hc= 5b83d60d, eac000a8: hc= 2c5a1e6b, eac000b8: hc= 5083198c, eac000c8: hc= 4f025f9f eac00038: hc= 00c5eb8a, eac00048: hc= 41eab16b, eac00058: hc= 1726099c, eac00068: hc= 4240eca3, eac00078: hc= 346fe350, eac00088: hc= 1db4b415, eac00098: hc= 429addef, eac000a8: hc= 45609812, eac000b8: hc= 489fe953, eac000c8: hc= 7a8f6d64 eac00038: hc= 7e628e42, eac00048: hc= 7869cfe0, eac00058: hc= 6aceb8e2, eac00068: hc= 29cc3436, eac00078: hc= 1d77daaa, eac00088: hc= 27b4de03, eac00098: hc= 535bab52, eac000a8: hc= 274cbf3f, eac000b8: hc= 1f9fd541, eac000c8: hc= 3669ae9f eac00038: hc= 772a3766, eac00048: hc= 749b46a8, eac00058: hc= 7e3bfb66, eac00068: hc= 13f62649, eac00078: hc= 054b8cdc, eac00088: hc= 230cc23b, eac00098: hc= 1aa3c177, eac000a8: hc= 74f2794a, eac000b8: hc= 5af92541, eac000c8: hc= 1afcfd10 eac00038: hc= 396e1dd8, eac00048: hc= 6c696d5c, eac00058: hc= 7d8aea9e, eac00068: hc= 2b316b76, eac00078: hc= 39862621, eac00088: hc= 16315e08, eac00098: hc= 03146a9a, eac000a8: hc= 3162a60a, eac000b8: hc= 4382f3da, eac000c8: hc= 4a578fd6 eac00038: hc= 225765b0, eac00048: hc= 17d5176d, eac00058: hc= 26f50154, eac00068: hc= 1f2a45c7, eac00078: hc= 104b1bcd, eac00088: hc= 330e3816, eac00098: hc= 6a844689, eac000a8: hc= 12330301, eac000b8: hc= 530a3ffc, eac000c8: hc= 45eee3fb eac00038: hc= 3f9432e0, eac00048: hc= 1a9830bc, eac00058: hc= 7da79447, eac00068: hc= 04f801c4, eac00078: hc= 363bed68, eac00088: hc= 185f62a9, eac00098: hc= 1e4651bf, eac000a8: hc= 1aa0e220, eac000b8: hc= 385db088, eac000c8: hc= 0ef0cda1 

अलग नोट के रूप में; यदि आप इस कोड को देखते हैं

 if (value == 0) value = 0xBAD ; 

ऐसा प्रतीत होता है कि 0xBAD दो बार जितना सामान्य हो उतना सामान्य होता है क्योंकि किसी भी हैशोड 0 को इस मान पर मैप किया जाता है। यदि आप इस लंबे समय तक चलते हैं तो आप देखेंगे

 long count = 0, countBAD = 0; while (true) { for (int i = 0; i < 200000000; i++) { int hc = new Object().hashCode(); if (hc == 0xBAD) countBAD++; count++; } System.out.println("0xBAD ratio is " + (double) (countBAD << 32) / count + " times expected."); } 

प्रिंट

 0xBAD ratio is 2.0183116992481205 times expected. 

वेब के समाधान से एकत्रित समाधान "जावा में "आंतरिक पता" क्या है?"

यह स्पष्ट रूप से कार्यान्वयन-विशिष्ट है।

नीचे मैं OpenJDK 7 में उपयोग किया गया Object.hashCode() . Object.hashCode() कार्यान्वयन शामिल करता हूं I

यह समारोह छह भिन्न गणना विधियों का समर्थन करता है, जिनमें से केवल दो ऑब्जेक्ट्स एड्रेस के नोटिस लेते हैं ("एड्रेस" जो कि सी ++ intptr_t को intptr_t डाला जाता है)। दो विधियों में से एक का पता पते के रूप में उपयोग करता है, जबकि दूसरा कुछ थोड़ी चक्कर लगाता है और फिर परिणाम को लगातार-अपडेट किए गए यादृच्छिक संख्या के साथ mashes।

शेष तरीकों में से, एक निरंतर (संभावित रूप से परीक्षण के लिए) देता है, एक अनुक्रमिक संख्या देता है, और शेष छद्म यादृच्छिक दृश्यों पर आधारित होते हैं।

ऐसा प्रतीत होता है कि विधि रनटाइम पर चुना जा सकता है, और डिफ़ॉल्ट विधि 0 लगता है, जो os::random() । उत्तरार्द्ध एक रैखिक congruential जनरेटर है , में कथित दौड़ की स्थिति के साथ फेंक दिया 🙂 दौड़ की स्थिति स्वीकार्य है क्योंकि सबसे खराब में एक ही हैश कोड साझा दो वस्तुओं का परिणाम होगा; यह किसी भी अपूर्वदृष्टियों को नहीं तोड़ता है

गणना एक हैश कोड की आवश्यकता है पहली बार किया जाता है। सुसंगतता बनाए रखने के लिए, परिणाम ऑब्जेक्ट के हेडर में संग्रहीत किया जाता है और hashCode() बाद के कॉलों पर वापस किया जाता है कैशिंग इस फ़ंक्शन के बाहर किया जाता है।

संक्षेप में, धारणा है कि Object.hashCode() ऑब्जेक्ट के पते पर आधारित है, काफी हद तक एक ऐतिहासिक कलाकृति है जिसे आधुनिक कचरा कलेक्टरों के गुणों से अप्रचलित कर दिया गया है।

 // hotspot/src/share/vm/runtime/synchronizer.hpp // hashCode() generation : // // Possibilities: // * MD5Digest of {obj,stwRandom} // * CRC32 of {obj,stwRandom} or any linear-feedback shift register function. // * A DES- or AES-style SBox[] mechanism // * One of the Phi-based schemes, such as: // 2654435761 = 2^32 * Phi (golden ratio) // HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ; // * A variation of Marsaglia's shift-xor RNG scheme. // * (obj ^ stwRandom) is appealing, but can result // in undesirable regularity in the hashCode values of adjacent objects // (objects allocated back-to-back, in particular). This could potentially // result in hashtable collisions and reduced hashtable efficiency. // There are simple ways to "diffuse" the middle address bits over the // generated hashCode values: // static inline intptr_t get_next_hash(Thread * Self, oop obj) { intptr_t value = 0 ; if (hashCode == 0) { // This form uses an unguarded global Park-Miller RNG, // so it's possible for two threads to race and generate the same RNG. // On MP system we'll have lots of RW access to a global, so the // mechanism induces lots of coherency traffic. value = os::random() ; } else if (hashCode == 1) { // This variation has the property of being stable (idempotent) // between STW operations. This can be useful in some of the 1-0 // synchronization schemes. intptr_t addrBits = intptr_t(obj) >> 3 ; value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ; } else if (hashCode == 2) { value = 1 ; // for sensitivity testing } else if (hashCode == 3) { value = ++GVars.hcSequence ; } else if (hashCode == 4) { value = intptr_t(obj) ; } else { // Marsaglia's xor-shift scheme with thread-specific state // This is probably the best overall implementation -- we'll // likely make this the default in future releases. unsigned t = Self->_hashStateX ; t ^= (t << 11) ; Self->_hashStateX = Self->_hashStateY ; Self->_hashStateY = Self->_hashStateZ ; Self->_hashStateZ = Self->_hashStateW ; unsigned v = Self->_hashStateW ; v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ; Self->_hashStateW = v ; value = v ; } value &= markOopDesc::hash_mask; if (value == 0) value = 0xBAD ; assert (value != markOopDesc::no_hash, "invariant") ; TEVENT (hashCode: GENERATE) ; return value; } 

यह आम तौर पर वस्तु का मेमोरी पता होता है हालांकि, पहली बार hashcode विधि को ऑब्जेक्ट पर बुलाया जाता है, पूर्णांक उस ऑब्जेक्ट के शीर्ष में संग्रहीत किया जाता है ताकि अगले आवंटन एक ही मान वापस कर सकें (जैसा कि आप कहते हैं, कचरा संग्रह को कम्पेक्ट करना पते को बदल सकता है)। मेरी जानकारी के लिए यह ओरेकल जेवीएम में कार्यान्वित किया जाता है।

संपादित करें: जेवीएम स्रोत कोड में खुदाई, यह दिखाया गया है (synchronizer.cpp):

 // hashCode() generation : // // Possibilities: // * MD5Digest of {obj,stwRandom} // * CRC32 of {obj,stwRandom} or any linear-feedback shift register function. // * A DES- or AES-style SBox[] mechanism // * One of the Phi-based schemes, such as: // 2654435761 = 2^32 * Phi (golden ratio) // HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ; // * A variation of Marsaglia's shift-xor RNG scheme. // * (obj ^ stwRandom) is appealing, but can result // in undesirable regularity in the hashCode values of adjacent objects // (objects allocated back-to-back, in particular). This could potentially // result in hashtable collisions and reduced hashtable efficiency. // There are simple ways to "diffuse" the middle address bits over the // generated hashCode values: // static inline intptr_t get_next_hash(Thread * Self, oop obj) { intptr_t value = 0 ; if (hashCode == 0) { // This form uses an unguarded global Park-Miller RNG, // so it's possible for two threads to race and generate the same RNG. // On MP system we'll have lots of RW access to a global, so the // mechanism induces lots of coherency traffic. value = os::random() ; } else if (hashCode == 1) { // This variation has the property of being stable (idempotent) // between STW operations. This can be useful in some of the 1-0 // synchronization schemes. intptr_t addrBits = intptr_t(obj) >> 3 ; value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ; } else if (hashCode == 2) { value = 1 ; // for sensitivity testing } else if (hashCode == 3) { value = ++GVars.hcSequence ; } else if (hashCode == 4) { value = intptr_t(obj) ; } else { // Marsaglia's xor-shift scheme with thread-specific state // This is probably the best overall implementation -- we'll // likely make this the default in future releases. unsigned t = Self->_hashStateX ; t ^= (t << 11) ; Self->_hashStateX = Self->_hashStateY ; Self->_hashStateY = Self->_hashStateZ ; Self->_hashStateZ = Self->_hashStateW ; unsigned v = Self->_hashStateW ; v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ; Self->_hashStateW = v ; value = v ; } value &= markOopDesc::hash_mask; if (value == 0) value = 0xBAD ; assert (value != markOopDesc::no_hash, "invariant") ; TEVENT (hashCode: GENERATE) ; return value; } 

तो ओरेकल जेवीएम में ऐसा करने के लिए 6 अलग-अलग तरीके हैं, इनमें से एक मेरे समकक्ष है जो मैंने कहा था … मूल्य ऑब्जेक्ट के शीर्ष लेख में get_next_hash (जिसे एक को FastHashCode कहा जाता है और इसे से फोन किया जाता है) में संग्रहीत किया जाता है Object.hashCode() मूल संस्करण Object.hashCode()

आईएमएचओ, यद्यपि कार्यान्वयन निर्भर है, जेवीएम में ऑब्जेक्ट संदर्भ कभी वास्तविक मेमोरी एड्रेस नहीं हैं, लेकिन आंतरिक जेवीएम संदर्भ जो वास्तविक पते को इंगित करते हैं। इन आंतरिक संदर्भ प्रारंभिक रूप से स्मृति पते पर आधारित होते हैं, लेकिन वे ऑब्जेक्ट से जुड़े रहते हैं जब तक इसे त्याग नहीं किया जाता है।

मैं यह कहता हूं क्योंकि जावा हॉटस्पॉट जीसी किसी फार्म या दूसरे के कलेक्टरों की प्रतिलिपि बना रहे हैं, और वे live objects और एक हीप से दूसरे की नकल करके काम करते हैं, बाद में old heap को नष्ट कर देते हैं। तो जब जीसी होता है, तो JVM को सभी ऑब्जेक्ट्स में संदर्भों को अपडेट नहीं करना पड़ता है, लेकिन आंतरिक संदर्भ में मैप किए गए वास्तविक मेमोरी एड्रेस को बदलना है।

ऑब्जेक्ट.hashCode () के लिए जवाडोक का सुझाव है कि इसे मेमोरी एड्रेस से हैशोड प्राप्त करने के द्वारा कार्यान्वित किया जाता है, केवल पुरानी है।

शायद कोई भी परेशान नहीं हुआ (या देखा गया) कि यह कार्यान्वयन पथ अब कचरा कलेक्टर कलेक्टर के साथ संभव नहीं है (चूंकि यह ऑब्जेक्ट किसी अन्य मेमोरी स्थान पर कॉपी किया गया है क्योंकि यह हैशोड बदल जाएगा)।

नकल कचरा कलेक्टर था, इससे पहले हैश कोड को लागू करने के लिए बहुत सारी भावनाएं पैदा हुई हैं, क्योंकि यह ढेर स्थान को बचाएगा। एक गैर प्रतिलिपि जीसी (सीएमएस) अभी भी आज हैश कोड लागू कर सकता है।