क्या जावा में इनलाइन फ़ंक्शन हैं?


112

क्या जावा में इनलाइन फ़ंक्शन की अवधारणा है, या इसकी जगह कुछ और है? यदि है, तो इसका उपयोग कैसे किया जाता है? मैंने सुना है कि public, staticऔर finalविधियाँ इनलाइन फ़ंक्शन हैं। क्या हम अपना इनलाइन फ़ंक्शन बना सकते हैं?


4
बस स्पष्ट करने के लिए, आपका मतलब है en.wikipedia.org/wiki/Inline_function , en.wikipedia.org/wiki/Anonymous_function , सही नहीं है?
जेडब्ल्यू।

3
एक छोटी सी टिप्पणी के रूप में, समय से पहले अनुकूलन सभी बुराई की जड़ है। सार्वजनिक, स्थिर और अंतिम की प्रकृति को पूरी तरह से समझने के बिना, आप वास्तव में इनलाइनिंग के प्रभाव को समझ नहीं सकते हैं - और यह आपके द्वारा उपयोग किए जा रहे जेवीएम पर निर्भर है। पहले जवाब देना सुनिश्चित करें कि आपको कुछ इनलाइन करने की आवश्यकता क्यों है: यह लगभग निश्चित है कि उच्च आरओआई अनुकूलन हैं जो आप कहीं और कर सकते हैं।
नाथनियल फोर्ड

1

जवाबों:


123

जावा में, अनुकूलन आमतौर पर जेवीएम स्तर पर किया जाता है। रनटाइम के दौरान, JVM इनलाइन निर्धारित करने के लिए कुछ "जटिल" विश्लेषण करता है। यह आक्रामक इनलाइनिंग हो सकता है, और हॉटस्पॉट जेवीएम वास्तव में गैर-अंतिम तरीकों को इनलाइन कर सकता है।

जावा कंपाइलर लगभग कभी भी किसी भी तरीके की कॉल को इनलाइन नहीं करता है (जेवीएम रनटाइम के दौरान वह सब करता है)। वे इनलाइन संकलन समय स्थिरांक (जैसे अंतिम स्थैतिक आदिम मान) करते हैं। लेकिन तरीके नहीं।

अधिक संसाधनों के लिए:

  1. लेख: जावा हॉटस्पॉट प्रदर्शन इंजन: विधि इनलाइनिंग उदाहरण

  2. विकी: OpenJDK में इनलाइनिंग , पूरी तरह से आबाद नहीं है लेकिन इसमें उपयोगी चर्चाओं के लिंक हैं।


15

नहीं, जावा में कोई इनलाइन फ़ंक्शन नहीं है । हां, आप किसी सार्वजनिक वर्ग में रखे जाने पर कोड में कहीं भी सार्वजनिक स्थैतिक विधि का उपयोग कर सकते हैं। जावा कंपाइलर स्थैतिक या अंतिम विधि पर इनलाइन विस्तार कर सकता है , लेकिन इसकी गारंटी नहीं है।

आमतौर पर ऐसे कोड ऑप्टिमाइज़ेशन कंपाइलर द्वारा JVM / JIT / HotSpot के साथ संयोजन में किए जाते हैं, जो कोड सेगमेंट में बहुत बार उपयोग किए जाते हैं। इसके अलावा अन्य अनुकूलन अवधारणाएं जैसे रजिस्टर घोषणाएं जावा में ज्ञात नहीं हैं।

अनुकूलन को जावा में घोषणा के द्वारा मजबूर नहीं किया जा सकता है, लेकिन संकलक और जेआईटी द्वारा किया जाता है। कई अन्य भाषाओं में, ये घोषणाएं अक्सर केवल संकलक संकेत होती हैं (आप प्रोसेसर से अधिक रजिस्टर पैरामीटर घोषित कर सकते हैं, बाकी को अनदेखा किया जाता है)।

संकलक के लिए स्थिर, अंतिम या निजी java विधियों की घोषणा भी संकेत है। आपको इसका उपयोग करना चाहिए, लेकिन कोई गारंटी नहीं। जावा प्रदर्शन गतिशील है, स्थिर नहीं है। क्लास लोडिंग के कारण सिस्टम पर पहला कॉल हमेशा धीमा होता है। अगली कॉलें तेज़ होती हैं, लेकिन मेमोरी और रनटाइम के आधार पर सबसे आम कॉल को रनिंग सिस्टम के साथ ऑप्टिमाइज़ किया जाता है, इसलिए रनटाइम के दौरान एक सर्वर तेज़ हो सकता है!


3
finalजेआईटी इनलाइनिंग पर कोई प्रभाव न
स्टीव कू

1
+1, लेकिन हम कैसे परीक्षण कर सकते हैं कि एक विधि का संकलित संस्करण इनलेट है?
पचेरियर

@ स्पेसर लेकिन हमें परीक्षण क्यों करना चाहिए कि क्या कुछ अंतर्निर्मित है?
आर्ने बर्मिस्टर

14

जावा मैन्युअल रूप से सुझाव देने का एक तरीका प्रदान नहीं करता है कि एक विधि को इनलाइन किया जाना चाहिए। जैसा कि @notnoop टिप्पणियों में कहता है, इनलाइनिंग आमतौर पर JVM द्वारा निष्पादन समय पर की जाती है।


3
अधिकांश जावा कंपाइलर कभी इनलाइन विधि कॉल नहीं करते हैं। ज्यादातर जेवीएम ऐसा करता है।
notnoop

स्पष्ट करने के लिए धन्यवाद। मुझे यकीन नहीं था कि वह किस चरण में हुआ, बिल्कुल। मैं अपनी पोस्ट को प्रतिबिंबित करने के लिए संपादित करूँगा।
थॉमस ओवंस

@ThomasOwens यह करता है, लेकिन यह सार्वजनिक नहीं हैjdk.internal.vm.annotation.ForceInline
यूजीन

4

आपने जो ऊपर कहा वह सही है। कभी-कभी अंतिम तरीकों को इनलाइन के रूप में बनाया जाता है, लेकिन जावा में इनलाइन फ़ंक्शन को स्पष्ट रूप से बनाने का कोई अन्य तरीका नहीं है।


5
अंतिम तरीकों को इनलाइन होने की गारंटी नहीं है।
थॉमस ओवंस

4
हॉटस्पॉट पर, जोड़ने से finalभी कोई फर्क नहीं पड़ता है कि क्या विधि इनबिल्ट है या नहीं।
टॉम हॉल्टिन -

4
@ थोमस - जिसके कारण मैंने कहा "कभी-कभी अंतिम तरीके ..."
ग्रीनमीनी

@ टॉमहॉटिन-टैक्लाइन आपके पास इसके लिए एक आधिकारिक स्रोत है? जहां तक ​​मुझे पता है, अंतिम तरीकों को एक प्रकार के गार्ड को नियोजित किए बिना इनलाइन किया जा सकता है, जिसका अर्थ है कि संशोधक बिना संशोधक की तुलना में विधि को अधिक कुशल बनाता है। मुझे पता है कि जब इनलाइन तय होती है तो जेवी आरवीएम इसे ध्यान में रखता है। क्या आप निश्चित हैं कि हॉटस्पॉट कुछ नहीं करता है?
Jannik Jochem 11:25

2

वास्तविक जीवन उदाहरण:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

फिर अन्य वर्गों में, यदि कोड समाप्त हो गया है तो मैं बाहर निकल सकता हूं। यदि मैं EXPIRED_ON चर को दूसरी कक्षा से संदर्भित करता हूं, तो निरंतर बाइट कोड के लिए इनलाइन है, जिससे कोड की सभी जगहों को ट्रैक करना बहुत मुश्किल हो जाता है जो समाप्ति की तारीख की जांच करता है। हालाँकि, यदि अन्य वर्ग isExpired () विधि को लागू करते हैं, तो वास्तविक विधि को कहा जाता है, जिसका अर्थ है कि एक हैकर isExpired विधि को दूसरे के साथ बदल सकता है जो हमेशा गलत रिटर्न देता है।

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

मेरे शोध से, यह नहीं किया जा सकता है। शायद कुछ Obfuscator उपकरण ऐसा कर सकते हैं, या, आप संकलन करने से पहले स्रोतों को संपादित करने के लिए अपनी निर्माण प्रक्रिया को संशोधित कर सकते हैं।

यह सिद्ध करने के लिए कि क्या नियंत्रण वर्ग से विधि संकलन के दौरान दूसरी कक्षा में इनलाइन की जाती है, क्लास क्लास में नियंत्रण वर्ग के बिना अन्य वर्ग को चलाने का प्रयास करें।


2

खैर, ऐसे तरीके हैं जिन्हें जावा में "इनलाइन" तरीके कहा जा सकता है, लेकिन जेवीएम पर निर्भर करता है। संकलित करने के बाद, यदि विधि का मशीन कोड 35 बाइट से कम है, तो इसे तुरंत इनलाइन विधि में स्थानांतरित किया जाएगा, यदि विधि का मशीन कोड 325 बाइट से कम है, तो इसे एक इनलाइन विधि में स्थानांतरित किया जा सकता है, यह jmm पर निर्भर करता है।


1
ये Oracle के VM के लिए डिफ़ॉल्ट मान हैं , देखें docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

इसलिए, ऐसा लगता है कि वहाँ कुछ भी नहीं है, लेकिन आप इस वर्कअराउंड का उपयोग अमरूद या एक समतुल्य फंक्शन क्लास कार्यान्वयन के लिए कर सकते हैं, क्योंकि यह क्लास बेहद सरल, पूर्व है:

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

हां, यह मृत कोड है कि केवल एक जटिल कोड ब्लॉक बनाने के लिए ({} के भीतर) कुछ विशिष्ट ऐसा करने के लिए कैसे करें जो हमें इसके लिए कोई भी विधि बनाने में परेशान न करे, एके इनलाइन!


एक उचित विचार की तरह लगता है। क्या आपके पास इसका एक संस्करण है जो Google सामान्य पुस्तकालयों का उपयोग नहीं करता है?
ragerdl

0

Java9 में एक "समय से आगे" कंपाइलर है जो रनटाइम के बजाय संकलन-समय पर कई अनुकूलन करता है, जिसे इनलाइनिंग के रूप में देखा जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.