2016-02-13 10 views
5

मैं समझाने के उद्देश्य से एक साधारण वर्ग मिल गया है:जावा कंपाइलर एक छोटी विधि को अनुकूलित क्यों नहीं कर रहा है?

public class Test { 

    public int test1() { 
     int result = 100; 
     result = 200; 
     return result; 
    } 

    public int test2() { 
     return 200; 
    } 
} 

बाईटकोड संकलक (javap -c Test.class द्वारा निरीक्षण किया) द्वारा उत्पादित निम्नलिखित है:

public int test1(); 
Code: 
    0: bipush  100 
    2: istore_1 
    3: sipush  200 
    6: istore_1 
    7: iload_1 
    8: ireturn 

public int test2(); 
Code: 
    0: sipush  200 
    3: ireturn 

संकलक क्यों के अनुकूलन नहीं है test2 विधि के लिए उत्पादित एक ही बाइटकोड विधि? मैं उम्मीद करता हूं कि कम से कम result चर के अनावश्यक प्रारंभ से बचें, यह मानना ​​आसान है कि मान 100 का उपयोग नहीं किया जाता है।

मैंने इसे ग्रहण कंपाइलर और javac दोनों के साथ देखा।

javac संस्करण: 1.8.0_72, जावा के साथ एक साथ JDK के हिस्से के रूप में स्थापित:

Java(TM) SE Runtime Environment (build 1.8.0_72-b15) 
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode) 
+6

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

+5

क्लासिक उत्तर यह है कि अनुकूलन JVM में किया जाता है (http://stackoverflow.com/questions/5981460/optimization-by-java-compiler) – wero

+0

@ruakh अच्छी टिप्पणी; जोड़ा कंपाइलर जानकारी। –

उत्तर

4

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

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

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

+0

हाँ - कम से कम लाइन नंबर की जानकारी खो जाएगी, इसलिए स्टैकट्रैक सटीक नहीं होगा; और डीबगिंग कठिन हो जाएगा। – ZhongYu

4

JVM बाईटकोड अनुकूलित होते हैं, कुछ एक कोड कैश कहा जाता है का निर्माण। सी ++ के विपरीत, जेवीएम आपके प्रोग्राम के बारे में बहुत सारे डेटा एकत्र कर सकता है, उदाहरण के लिए, लूप के लिए कितना गर्म है?, क्या कोड कोड भी अनुकूलन के लायक है?, आदि। तो यहां अनुकूलन बहुत उपयोगी है, और अक्सर बेहतर परिणाम उत्पन्न करते हैं।

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

उदाहरण के रूप में, मान लें कि आपका प्रोग्राम एईएस एन्क्रिप्शन का उपयोग करता है। आधुनिक सीपीयू में एईएस-विशिष्ट निर्देश सेट होते हैं, विशेष हार्डवेयर के साथ एन्क्रिप्शन बहुत तेज हो जाता है।

तो javac यह या तो

  • का अनुकूलन एक सॉफ्टवेयर स्तर पर दिए गए निर्देशों का, जिस स्थिति में आप आधुनिक CPUs से अभ्यस्त लाभ कार्यक्रम, या,
  • का स्थान ले लेगा, संकलन समय पर अनुकूलन करने के लिए प्रयास करता है तो समकक्ष CPU-AES निर्देशों के साथ आपके एईएस निर्देश, केवल नए CPUs पर समर्थित हैं, जो आपकी संगतता को कम कर देंगे।

बजाय javac उन्हें छोड़ देता है के रूप में byptcode में है, तो JVM नए CPUs पर चल रहा है उन्हें एईएस के रूप में पहचान है और इस सीपीयू क्षमता दोहन कर सकते हैं, जबकि पुराने सीपीयू पर चल JVMs उन्हें एक सॉफ्टवेयर स्तर पर अनुकूलन कर सकते हैं रनटाइम (कोड कैश) पर, आपको इष्टतमता और संगतता दोनों प्रदान करते हैं।

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