2012-01-11 41 views
29

जावा में, वहाँ एक तरह से संदर्भ का पता पाने के लिए कहते हैं किक्या कोई संदर्भ पता प्राप्त करने का कोई तरीका है?

String s = "hello" 

मैं एस के पते प्राप्त कर सकते हैं अपने आप में भी, मैं जिस वस्तु संदर्भ को संदर्भित करता है, उसका पता प्राप्त कर सकते हैं?

+0

कृपया निर्दिष्ट करें कि पते के साथ आपका क्या मतलब है? स्मृति में पता? कचरा कलेक्टर-आईडी? – yankee

+0

आपको इसकी आवश्यकता क्यों है? – jarnbjo

+0

या तो मेमोरी या कचरा कलेक्टर आईडी –

उत्तर

7

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

आप ऐसी चीज क्यों चाहेंगे? यह जरूरी नहीं है कि आप किसी भी रूप में, मूल कोड से भी, किसी भी चीज़ के लिए उपयोग कर सकें।

+0

बस यह सुनिश्चित करना चाहते हैं कि कुछ संदर्भ समान हैं। –

+11

यदि आप दो संदर्भों की तुलना करना चाहते हैं, तो आप इसे == के साथ कर सकते हैं। ऑब्जेक्ट का पता पाने के लिए आपको कोई आवश्यकता नहीं है। – jarnbjo

4

नहीं, आप नहीं कर सकते। खासतौर पर जावा के रूप में नहीं (और AFAIK करता है) कचरा संग्रह के दौरान मेमोरी कॉम्पैक्टिंग के लिए आवश्यक होने पर ढेर में वस्तुओं को स्थानांतरित करता है।

आपको इसकी आवश्यकता क्यों है या चाहिए?

2

असल में पते sun.misc.Unsafe के साथ प्राप्त किया जा सकता है लेकिन यह वास्तव में बहुत असुरक्षित है। जीसी अक्सर वस्तुओं को स्थानांतरित करता है।

+1

पीटर लॉरी को मेरी टिप्पणी में पोस्ट किया गया लिंक दिखाता है कि आप इसे कैसे कर सकते हैं, जैसे कि आप सही पते को बनाए रख सकते हैं (कारण यदि आप मेमोरी आवंटन का उपयोग करके ऑब्जेक्ट्स बनाते हैं, तो आप शायद तकनीकी रूप से ढेर के बाहर हो सकते हैं, जहां जीसी प्रभावित नहीं करेगा आप)। मुझे लगता है कि टेराकोटा की बिगमेमरी कैसे काम करती है। –

31

आप ऑब्जेक्ट इंडेक्स को असुरक्षित के साथ प्राप्त कर सकते हैं। जेवीएम मेमोरी का उपयोग कर रहा है (32-बिट पते, 32-बिट इंडेक्स, ऑफसेट के साथ 32-बिट इंडेक्स, 64-बिट एड्रेस) इस बात पर निर्भर करता है कि ऑब्जेक्ट इंडेक्स कितना उपयोगी है।

यहां एक प्रोग्राम है जो मानता है कि आपके पास 64-बिट JVM में 32-बिट इंडेक्स है।

import sun.misc.Unsafe; 

import java.lang.reflect.Field; 
import java.util.Arrays; 
import java.util.Collections; 

public class OrderOfObjectsAfterGCMain { 
    static final Unsafe unsafe = getUnsafe(); 
    static final boolean is64bit = true; // auto detect if possible. 

    public static void main(String... args) { 
     Double[] ascending = new Double[16]; 
     for(int i=0;i<ascending.length;i++) 
      ascending[i] = (double) i; 

     Double[] descending = new Double[16]; 
     for(int i=descending.length-1; i>=0; i--) 
      descending[i] = (double) i; 

     Double[] shuffled = new Double[16]; 
     for(int i=0;i<shuffled.length;i++) 
      shuffled[i] = (double) i; 
     Collections.shuffle(Arrays.asList(shuffled)); 

     System.out.println("Before GC"); 
     printAddresses("ascending", ascending); 
     printAddresses("descending", descending); 
     printAddresses("shuffled", shuffled); 

     System.gc(); 
     System.out.println("\nAfter GC"); 
     printAddresses("ascending", ascending); 
     printAddresses("descending", descending); 
     printAddresses("shuffled", shuffled); 

     System.gc(); 
     System.out.println("\nAfter GC 2"); 
     printAddresses("ascending", ascending); 
     printAddresses("descending", descending); 
     printAddresses("shuffled", shuffled); 
    } 

    public static void printAddresses(String label, Object... objects) { 
     System.out.print(label + ": 0x"); 
     long last = 0; 
     int offset = unsafe.arrayBaseOffset(objects.getClass()); 
     int scale = unsafe.arrayIndexScale(objects.getClass()); 
     switch (scale) { 
      case 4: 
       long factor = is64bit ? 8 : 1; 
       final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor; 
       System.out.print(Long.toHexString(i1)); 
       last = i1; 
       for (int i = 1; i < objects.length; i++) { 
        final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor; 
        if (i2 > last) 
         System.out.print(", +" + Long.toHexString(i2 - last)); 
        else 
         System.out.print(", -" + Long.toHexString(last - i2)); 
        last = i2; 
       } 
       break; 
       case 8: 
        throw new AssertionError("Not supported"); 
     } 
     System.out.println(); 
    } 

    private static Unsafe getUnsafe() { 
     try { 
      Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 
      theUnsafe.setAccessible(true); 
      return (Unsafe) theUnsafe.get(null); 
     } catch (Exception e) { 
      throw new AssertionError(e); 
     } 
    } 
} 

जावा 6 अद्यतन 26 और जावा 7. नोट (साथ उफ़ संकुचित 64-बिट) पर चल रहा है: पते और रिश्तेदार के पते हेक्स में हैं।

Before GC 
ascending: 0x782322b20, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18 
descending: 0x782322e58, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18 
shuffled: 0x782322ec0, +78, -30, +90, -c0, +18, +90, +a8, -30, -d8, +f0, -30, -90, +60, -48, +60 

After GC 
ascending: 0x686811590, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18 
descending: 0x686811410, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18 
shuffled: 0x686811290, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18 

या कभी कभी

Before GC 
ascending: 0x782322b20, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18 
descending: 0x782322e58, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18 
shuffled: 0x782323028, -168, +150, -d8, -30, +60, +18, +30, +30, +18, -108, +30, -48, +78, +78, -30 

After GC 
ascending: 0x6868143c8, +4db0, +7120, -bd90, +bda8, -bd90, +4d40, +18, +18, -12710, +18, +80, +18, +ffa8, +220, +6b40 
descending: 0x68681d968, +18, +d0, +e0, -165d0, +a8, +fea8, +c110, -5230, -d658, +6bd0, +be10, +1b8, +75e0, -19f68, +19f80 
shuffled: 0x686823938, -129d8, +129f0, -17860, +4e88, +19fe8, -1ee58, +18, +18, +bb00, +6a78, -d648, -4e18, +4e40, +133e0, -c770 
+2

++ अच्छी नौकरी। इसे किसी अन्य एसओ लिंक से इंगित करने जा रहा था: http://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe, लेकिन आपने दिखाया कि इसे कोड के साथ कैसे करना बेहतर है। –

+2

यह साफ सामान है, लेकिन पाठकों को यह समझने की देखभाल करनी चाहिए कि यह पोर्टेबल नहीं है; 'असुरक्षित' वर्ग सूर्य-व्युत्पन्न जेवीएम का एक अनियंत्रित कार्यान्वयन विवरण है। यह कोड जे 9, जेआरॉकिट, डाल्विक आदि पर काम नहीं करेगा। –

+0

@ पीटर लेवर क्या 32-बिट और 64-बिट चीज़ के बारे में कोई विस्तृत स्पष्टीकरण है? मुझे उसमें बहुत दिलचस्पी है। – dawnstar

1

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

सी में, आप पॉइंटर्स की अवधारणा के माध्यम से ऐसा कर सकते हैं। जावा के पास निम्न स्तर पर एक समान अवधारणा है, और यह संदर्भ पता है। संदर्भ एक सी सूचक की तरह है, लेकिन यह स्पष्ट नहीं है। सी में, आप * के माध्यम से पॉइंटर्स के संदर्भ के संचालन के संचालन कर सकते हैं, लेकिन जावा में, यह संभव नहीं है।

मुझे सी भाषा बहुत पसंद नहीं है, क्योंकि मेरे अनुसार पॉइंटर्स, प्रबंधन के लिए एक आसान अवधारणा नहीं हैं। यह जावा कारणों में से एक कारण है, क्योंकि प्रोग्रामर को ऑब्जेक्ट के पॉइंटर के बारे में चिंता करने की आवश्यकता नहीं है।

@jarnbjo कहते हैं की तरह, आप जाँच कर सकते हैं, अगर कुछ संदर्भों समान हैं, इस तरह एक वाक्य रचना के साथ:

String s = "hello"; 
String g = s; 
System.out.println("Are the reference addresses similar? "+(s==g)); 
g = "goodbye"; 
System.out.println("Are the reference addresses similar? "+(s==g)); 

ध्यान दें कि == चेकों संदर्भ पते की समानता। यदि आप तारों के मूल्य की समानता की जांच करना चाहते हैं, तो equals() विधि का उपयोग करें।

मैं आपको this SO प्रश्न, this विकिपीडिया पृष्ठ और this पृष्ठ पढ़ने का सुझाव देता हूं।

3

हां, आप इसे असुरक्षित के साथ कर सकते हैं, Althrough यह इतना सीधे नहीं है। ऑब्जेक्ट या इंस्टेंस संदर्भ को int [] में रखें, यह ठीक है। लंबे [] ठीक भी होना चाहिए।

@Test 
public void test1() throws Exception { 
    Unsafe unsafe = Util.unsafe; 
    int base = unsafe.arrayBaseOffset(int[].class); 
    int scale = unsafe.arrayIndexScale(int[].class); 
    int shift = 31 - Integer.numberOfLeadingZeros(scale); 
    System.out.printf("base: %s, scale %s, shift: %s\n", base, scale, shift); 
    base = unsafe.arrayBaseOffset(Object[].class); 
    scale = unsafe.arrayIndexScale(Object[].class); 
    shift = 31 - Integer.numberOfLeadingZeros(scale); 
    System.out.printf("base: %s, scale %s, shift: %s\n", base, scale, shift); 
    int[] ints = { 1, 2, 0 }; 
    String string = "abc"; 
    System.out.printf("string: id: %X, hash: %s\n", System.identityHashCode(string), string.hashCode()); 
    unsafe.putObject(ints, offset(2, shift, base), string); 
    System.out.printf("ints: %s, %X\n", Arrays.toString(ints), ints[2]); 
    Object o = unsafe.getObject(ints, offset(2, shift, base)); 
    System.out.printf("ints: %s\n", o); 
    assertSame(string, o); 

    Object[] oa = { 1, 2, string }; 
    o = unsafe.getObject(oa, offset(2, shift, base)); 
    assertSame(string, o); 
    int id = unsafe.getInt(oa, offset(2, shift, base)); 
    System.out.printf("id=%X\n", id); 
} 

public static long offset(int index, int shift, int base) { 
    return ((long) index << shift) + base; 
} 
+1

पर एक अच्छा लिंक है, इन कक्षाओं के पैकेज क्या हैं? –

+0

sun.misc.Unsafe। एचजी openjdk.java.net। JDK \ src \ शेयर \ वर्गों \ सूरज \ विविध \ Unsafe.java – qinxian

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

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