2011-10-28 6 views
6

मैं sun.misc.Unsafe के प्रलेखन को समझने के लिए संघर्ष कर रहा हूं - मुझे लगता है क्योंकि यह सामान्य उपयोग के लिए नहीं है, कोई भी इसे पढ़ने योग्य बनाने के लिए वास्तव में परेशान नहीं है - लेकिन मुझे वास्तव में वास्तव में एक पते का पता लगाने के लिए एक तरीका चाहिए एक सरणी में तत्व (ताकि मैं मूल कोड पर पॉइंटर पास कर सकूं)। क्या किसी को कोई कामकाजी कोड मिला है जो यह करता है? क्या यह विश्वसनीय है?जावा सरणी वस्तुओं का पता पाने के लिए sun.misc.Unsafe का उपयोग करना?

+0

http://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe –

+0

[डेवलपर्स को प्रोग्राम क्यों नहीं लिखना चाहिए कॉल 'सूर्य' पैकेज] (http://www.oracle .com/technetwork/जावा/faq-sun-packages-142232.html) – BalusC

+0

आईएमओ, असुरक्षित दस्तावेज़ बहुत अच्छा है, यह किसी भी तरह के आम जनता के लिए नहीं है। अगर आपको कुछ दिशानिर्देशों की आवश्यकता है, तो java.util.concurrent और java.util.concurrent.atomic पढ़ने शुरू करें ... असुरक्षित सी (या असेंबलर, यदि आप चाहें) के बहुत करीब हैं। यदि आपके पास कोई अनुभव नहीं है, तो असुरक्षित आपके लिए नहीं है। अपने जावा कोड को कैसे डिस्सेबल करें: http://wikis.sun.com/display/HotSpotInternals/PrintAssembly – bestsss

उत्तर

6

एक सरणी का उपयोग करने के बजाय आप एक ByteBuffer.allocateDirect() प्रत्यक्ष बफर का उपयोग कर सकते हैं। इस क्षेत्र में पता है और यह पता बाइटबफर के जीवन के लिए नहीं बदलता है। एक प्रत्यक्ष बाइटबफर न्यूनतम ढेर अंतरिक्ष का उपयोग करता है। आप प्रतिबिंब का उपयोग कर पता प्राप्त कर सकते हैं।


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

जेएनआई में आप इस समस्या से बचने के लिए जावा ऑब्जेक्ट्स से डेटा कॉपी करने के लिए विशेष तरीकों का उपयोग कर सकते हैं (और अन्य) मेरा सुझाव है कि आप इनका उपयोग करते हैं यदि आप सी कोड के साथ ऑब्जेक्ट्स के बीच डेटा का आदान-प्रदान करना चाहते हैं।

+1

मैं प्रत्यक्ष बाइट बफर का उपयोग नहीं करना चाहूंगा (जो समस्या को सुलझाने में आसान होगा) क्योंकि मैं बाइट एरे के संदर्भ में परिभाषित एक मौजूदा एपीआई को कार्यान्वित करने की कोशिश कर रहा हूं, और प्रतिलिपि बनाने के जुर्माना से बचने की कोशिश कर रहा हूं और बफर के एक अतिरिक्त सेट से। यह एक अंतिम उपाय के रूप में पर्याप्त होगा, लेकिन कुछ बेहतर तरीका होना चाहिए। जेएनआई के साथ काम करना यह आसान बना देगा, लेकिन दुर्भाग्यवश मैं जेएनए के साथ काम कर रहा हूं, ऐसा लगता है कि पूरे सरणी के साथ काम करने के अलावा अन्य कुछ भी करने के लिए इंटरफेस आवश्यक नहीं है। – Jules

+0

@ जुल्स, जेएनआई अपने आप पर एक प्रतिलिपि बनायेगा, जब तक कि आप w/'GetPrimitiveArrayCritical' नहीं जाना चाहते हैं जो जीसी को चोट पहुंचा सकता है। बुलेट को काट लें और सीधे (बफर) मेमोरी में कॉपी करें। यह एकमात्र व्यवहार्य समाधान है। उदाहरण के लिए प्रत्यारोपण। FileOutputStream (सॉकेटऑटपुटस्ट्रीम इसे विस्तारित करता है) स्टैक पर तत्वों की प्रति का उपयोग करता है। प्रतिलिपि के लिए जुर्माना इतना अधिक नहीं है, क्योंकि उच्चतम लागत डेटा की भार लागत (और कैश मिस, यहां तक ​​कि) है जो आपको किसी भी तरह का भुगतान करना होगा। प्रतिलिपि से भी cachelines prefetch का कारण बन जाएगा, इसलिए यह भी बेहतर हो सकता है कि मूल कोड कैसे काम करता है। – bestsss

+0

@ जुल्स, एक तरफ ध्यान दें: यहां तक ​​कि javax.net.ssl.SSLEngine बफर का उपयोग करने की अनुमति देता है, सभी एल्गोरिदम बाइट [] हैं और वे प्रत्यक्ष बफर को अस्थायी सरणी में कॉपी करते हैं, यह विपरीत कहानी और इसके नैतिक है : प्रत्यक्ष बफर w/SSLEngine का उपयोग न करें। – bestsss

6

यहां एक कामकाजी नमूना है। कृपया सावधान रहें, हालांकि Unsafe कक्षा के अनुचित उपयोग के साथ आप आसानी से अपने JVM को क्रैश कर सकते हैं।

import java.lang.reflect.Field; 

import sun.misc.Unsafe; 

public class UnsafeTest { 

    public static void main(String... args) { 
     Unsafe unsafe = null; 

     try { 
      Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); 
      field.setAccessible(true); 
      unsafe = (sun.misc.Unsafe) field.get(null); 
     } catch (Exception e) { 
      throw new AssertionError(e); 
     } 

     int ten = 10; 
     byte size = 1; 
     long mem = unsafe.allocateMemory(size); 
     unsafe.putAddress(mem, ten); 
     long readValue = unsafe.getAddress(mem); 
     System.out.println("Val: " + readValue); 

    } 
} 
+2

वह कोड पूरी तरह से सुरक्षित होना चाहिए, क्योंकि यह बिल्कुल सही है कि DirectByteBuffer कैसे काम करता है। दुर्भाग्य से, यह वही नहीं करता जो मैं चाहता हूं, जो किसी मौजूदा सरणी में डेटा तक पहुंचना है। – Jules

+4

@StephenC, कोड पूरी तरह से ठीक है, यह मूल रूप से 'char * mem = malloc (आकार) है; ... 'यह कभी भी जीसी द्वारा छुआ नहीं जाता है और वास्तविक सी रिसाव का कारण बनता है। – bestsss

+2

कोड ठीक है, लेकिन आपको आवंटित स्मृति को मुक्त करने पर भी विचार करने की आवश्यकता है। इसे करने के एक तरीके के लिए DirectByteBuffer देखें। यह भी मान लें कि आवंटित स्मृति शून्य नहीं है, इसलिए आप मान सकते हैं कि आपकी सीधी सरणी शून्य प्रारंभ नहीं है। –

1

क्यों? जावा सरणी की सामग्री से निपटने के लिए जेएनआई में बहुत सारी सुविधाएं हैं। आपको अनियंत्रित आंतरिक सूर्य वर्गों का उपयोग करने की आवश्यकता नहीं है जो अगले हफ्ते नहीं हो सकते हैं।

+0

मैं जेएनआई के बजाए जेएनए का उपयोग कर रहा हूं, और जिस फ़ंक्शन को मैं एक सरणी के बीच में एक पॉइंटर पास करने की आवश्यकता के साथ इंटरफेसिंग कर रहा हूं, जबकि जेएनए केवल एक सरणी की शुरुआत में सूचक उत्पन्न करने में सक्षम प्रतीत होता है। – Jules

+0

@ जुल्स, जेएनए और सामान्य सरणी मिश्रण न करें, सीधे बफर का उपयोग करें। – bestsss

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