2016-10-15 13 views
6

के दो कार्यान्वयनों में से एक का उपयोग करके संकलित करता है मैं जावा में कुछ एफएफआई कोड लिख रहा हूं जो sun.misc.Unsafe का भारी उपयोग करता है।जावा कोड लिखना जो कक्षा

जावा 9 में, यह कक्षा अप्राप्य हो जाएगी, और jdk.unsupported.Unsafe बन जाएगी। मैं अपना कोड लिखना चाहता हूं ताकि यह अब काम कर सके, लेकिन जावा 9 में काम करना जारी रखता है।

ऐसा करने के लिए कम से कम हैकी तरीका क्या है? मैं बाइनरी संगतता पसंद करूंगा, लेकिन स्रोत संगतता भी ठीक है।

संपादित करें: प्रतिबिंब का उपयोग करने के साथ मैं 100% ठीक नहीं हूं - या यहां तक ​​कि आभासी प्रेषण - हर बार Unsafe पर एक विधि कहा जाता है। उन तरीकों में से अधिकांश एक मशीन निर्देश पर संकलित करें। इसलिए, प्रदर्शन वास्तव में मायने रखता है। रैपर होने के लिए ठीक है - लेकिन केवल अगर मैं सुनिश्चित कर सकता हूं कि जेआईटी उन्हें हर समय इनलाइन करेगी।

मेरी वर्तमान योजना रनटाइम पर उचित कक्षा लोड करना है।

+0

यह 'असमर्थित 'होगा ... – r1verside

+0

@ r1verside मुझे पता है, लेकिन यह लगभग निश्चित नहीं है कि दूर जाना न जाए, क्योंकि इतना कोड (नया विकास सहित!) इस पर निर्भर करता है। – Demi

+0

हो सकता है कि ऐसा करने का समय हो जो आपको बहुत समय पहले करना चाहिए था: अपना कोड ठीक करें (इसलिए आप किसी भी gnarly पुराने सूर्य कोड का उपयोग नहीं करते हैं)। – Bohemian

उत्तर

2

एक विकल्प: आप असुरक्षित पर विधि (रों) है कि आप के लिए उपयोग की जरूरत के लिए एक छोटा सा शिम सहायक इंटरफेस हो सकता था, दो कार्यान्वयन के साथ: sun.misc.Unsafe के लिए एक और के लिए एक नया jdk.unsupported.Unsafe। दोनों वर्गों को आपके जेएआर में द्विआधारी संसाधनों के रूप में संग्रहीत किया जा सकता है, और कक्षा प्रारंभिकरण (यानी, static ब्लॉक में) के दौरान आप एक नया क्लासलोडर बना सकते हैं और शिम वर्ग लोड कर सकते हैं। यह कक्षा प्रारंभिकरण के दौरान आपको कुछ प्रतिबिंबित ओवरहेड देगा, लेकिन रनटाइम पर कोई प्रतिबिंब शामिल नहीं है, केवल एक वर्चुअल विधि प्रेषण - जिसे जेआईटी इनलाइन करने में सक्षम होना चाहिए, जब तक कि आप केवल एक कार्यान्वयन वर्ग लोड न करें।

यदि आप लाइब्रेरी निर्भरता पेश कर सकते हैं, तो cglib's FastClass मूल रूप से बहुत कम प्रयास के साथ आपके लिए ऐसा करेगा।

हमेशा निम्न स्तर के प्रदर्शन हैक्स के साथ इस तरह, आपको कुछ डेटा चाहिए। इसके लिए एक जेएमएच परीक्षण दोहन बनाएं और सत्यापित करें कि प्रतिबिंब ओवरहेड वास्तव में असहिष्णु है, और यह कि जेआईटी वास्तव में आपके समाधान को रेखांकित कर सकता है - यह निश्चित होने का एकमात्र तरीका है।

0

एक तरीका ऐसा वर्ग लिखना होगा जो कार्यान्वयन को लपेटता है और सही कार्यान्वयन के लिए एक सहायक विधि का उपयोग करता है। आप System.getProperties() प्राप्त कर सकते हैं। GetProperty ("java.version") यह जानने के लिए कि क्या आप जेडीके 1.8 या 1.9 में हैं या आप कक्षा को पाने के लिए बस कोशिश/पकड़ सकते हैं।

दुर्भाग्य से कार्यान्वित करने के लिए कोई इंटरफेस नहीं है, इसलिए आपको इसे सादे ऑब्जेक्ट की तरह उपयोग करना होगा। आपको हर विधि को लपेटना होगा। शायद ऐसा करने के लिए एक और सामान्य तरीका है। कार्यान्वयन की

उदाहरण शुरू

/** 
* A wrapper to a sun.misc.Unsafe or jdk.unsupported.Unsafe object. 
*/ 
public class MyUnsafe { 

    // the implementing class (sun.misc.Unsafe or jdk.unsupported.Unsafe) 
    private Class<?> unsafeCls; 

    // an instance of the implementing class 
    private Object unsafeObj; 

    // constructor 
    public MyUnsafe() throws InstantiationException, IllegalAccessException { 
     unsafeCls = getImplClass(); 
     unsafeObj = unsafeCls.newInstance(); 
    } 

    // get the implementing class 
    private Class<?> getImplClass() { 
     Class<?> implClass = null; 
     try { 
      // JDK 1.8 and earlier 
      implClass = Class.forName("sun.misc.Unsafe"); 
     } 
     catch (ClassNotFoundException e1) { 
      try { 
       // JDK 1.9 and later 
       implClass = Class.forName("jdk.unsupported.Unsafe"); 
      } 
      catch (ClassNotFoundException e2) { 
       // TODO - something that wraps both e1 and e2 
       throw new RuntimeException(e2); 
      } 
     } 
     return implClass; 
    } 

    // Wrap methods 

    // for example 
    public Object getObject(Object obj, long offset) throws Exception { 
     Method mtd = unsafeCls.getMethod("getObject", new Class<?>[] { Object.class, long.class }); 
     return mtd.invoke(unsafeObj, new Object[] { obj, offset }); 
    } 

    // and so on... 
} 
+1

यह काम नहीं करेगा। प्रत्येक विधि आमंत्रण पर प्रतिबिंब ओवरहेड प्रदर्शन को मार देगा। मुझे ऐसा कुछ चाहिए जो जेआईटी को रैपर को रेखांकित करने की अनुमति देता है - जेडीके संस्करण के आधार पर एक वर्ग या दूसरे को लोड करने की लाइनों के साथ कुछ। – Demi

+0

क्या आप प्रदर्शन के बारे में निश्चित हैं? मेरे अनुभव प्रतिबिंब में जावा द्वारा किए गए सामान्य आंतरिक जांच की तुलना में इतना धीमा नहीं है। – pmcevoy12

0

नि: शुल्क तकनीक समाधान, निश्चित रूप से दस्तावेज करना होगा कि आपकी लाइब्रेरी जावा 9 के साथ असंगत है, और एक अलग संस्करण शाखा जारी करती है जो जावा 9 पर काम करती है (लेकिन पिछले संस्करणों पर नहीं)। यह आपके ग्राहकों को समस्या को धक्का देता है, लेकिन वास्तविक दुनिया के उपयोग के अधिकांश मामलों के लिए यह काफी अच्छा होने की संभावना है।

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