यह मज़बूती से पुन: पेश किया जा सकता है (या पुन: प्रस्तुत नहीं किया जा सकता है, इस पर निर्भर करता है कि आप क्या चाहते हैं) openjdk version "1.8.0_222"
(मेरे विश्लेषण में इस्तेमाल किया गया ) के साथ , 12.0.1
ओपनजेडीके (ओलेकेंडर पायरोव के अनुसार) और ओपनजेडके 13 (कार्लोस हेबरगर के अनुसार)।
मैंने -XX:+PrintCompilation
दोनों व्यवहार प्राप्त करने के लिए पर्याप्त समय के साथ कोड चलाया और यहां अंतर हैं।
छोटी गाड़ी कार्यान्वयन (उत्पादन प्रदर्शित करता है):
--- Previous lines are identical in both
54 17 3 java.lang.AbstractStringBuilder::<init> (12 bytes)
54 23 3 LoopOutPut::test (57 bytes)
54 18 3 java.lang.String::<init> (82 bytes)
55 21 3 java.lang.AbstractStringBuilder::append (62 bytes)
55 26 4 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
55 20 3 java.lang.StringBuilder::<init> (7 bytes)
56 19 3 java.lang.StringBuilder::toString (17 bytes)
56 25 3 java.lang.Integer::getChars (131 bytes)
56 22 3 java.lang.StringBuilder::append (8 bytes)
56 27 4 java.lang.String::equals (81 bytes)
56 10 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) made not entrant
56 28 4 java.lang.AbstractStringBuilder::append (50 bytes)
56 29 4 java.lang.String::getChars (62 bytes)
56 24 3 java.lang.Integer::stringSize (21 bytes)
58 14 3 java.lang.String::getChars (62 bytes) made not entrant
58 33 4 LoopOutPut::test (57 bytes)
59 13 3 java.lang.AbstractStringBuilder::append (50 bytes) made not entrant
59 34 4 java.lang.Integer::getChars (131 bytes)
60 3 3 java.lang.String::equals (81 bytes) made not entrant
60 30 4 java.util.Arrays::copyOfRange (63 bytes)
61 25 3 java.lang.Integer::getChars (131 bytes) made not entrant
61 32 4 java.lang.String::<init> (82 bytes)
61 16 3 java.util.Arrays::copyOfRange (63 bytes) made not entrant
61 31 4 java.lang.AbstractStringBuilder::append (62 bytes)
61 23 3 LoopOutPut::test (57 bytes) made not entrant
61 33 4 LoopOutPut::test (57 bytes) made not entrant
62 35 3 LoopOutPut::test (57 bytes)
63 36 4 java.lang.StringBuilder::append (8 bytes)
63 18 3 java.lang.String::<init> (82 bytes) made not entrant
63 38 4 java.lang.StringBuilder::append (8 bytes)
64 21 3 java.lang.AbstractStringBuilder::append (62 bytes) made not entrant
सही रन (कोई प्रदर्शन नहीं):
--- Previous lines identical in both
55 23 3 LoopOutPut::test (57 bytes)
55 17 3 java.lang.AbstractStringBuilder::<init> (12 bytes)
56 18 3 java.lang.String::<init> (82 bytes)
56 20 3 java.lang.StringBuilder::<init> (7 bytes)
56 21 3 java.lang.AbstractStringBuilder::append (62 bytes)
56 26 4 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
56 19 3 java.lang.StringBuilder::toString (17 bytes)
57 22 3 java.lang.StringBuilder::append (8 bytes)
57 24 3 java.lang.Integer::stringSize (21 bytes)
57 25 3 java.lang.Integer::getChars (131 bytes)
57 27 4 java.lang.String::equals (81 bytes)
57 28 4 java.lang.AbstractStringBuilder::append (50 bytes)
57 10 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) made not entrant
57 29 4 java.util.Arrays::copyOfRange (63 bytes)
60 16 3 java.util.Arrays::copyOfRange (63 bytes) made not entrant
60 13 3 java.lang.AbstractStringBuilder::append (50 bytes) made not entrant
60 33 4 LoopOutPut::test (57 bytes)
60 34 4 java.lang.Integer::getChars (131 bytes)
61 3 3 java.lang.String::equals (81 bytes) made not entrant
61 32 4 java.lang.String::<init> (82 bytes)
62 25 3 java.lang.Integer::getChars (131 bytes) made not entrant
62 30 4 java.lang.AbstractStringBuilder::append (62 bytes)
63 18 3 java.lang.String::<init> (82 bytes) made not entrant
63 31 4 java.lang.String::getChars (62 bytes)
हम एक महत्वपूर्ण अंतर देख सकते हैं। सही निष्पादन के साथ हम test()
दो बार संकलन करते हैं । एक बार शुरुआत में, और एक बार फिर बाद में (संभवतः क्योंकि जेआईटी नोटिस करता है कि विधि कितनी गर्म है)। बग्गी में निष्पादन 5 बार test()
संकलित (या विघटित) होता है।
इसके अतिरिक्त, के साथ चल रहा -XX:-TieredCompilation
है (जो या तो व्याख्या या का उपयोग करता है C2
) या के साथ -Xbatch
(समांतर है, जो मुख्य थ्रेड में चलाने के लिए संकलन बलों के बजाय), उत्पादन कर रहा है की गारंटी और सामान का एक बहुत बाहर 30000 पुनरावृत्तियों प्रिंट के साथ है, तो C2
संकलक लगता है अपराधी होना। इसके साथ चलने की पुष्टि की जाती है -XX:TieredStopAtLevel=1
, जो निष्क्रिय करता है C2
और उत्पादन नहीं करता है (स्तर 4 पर रोकना बग को फिर से दिखाता है)।
सही निष्पादन में, विधि पहले स्तर 3 संकलन के साथ संकलित की जाती है , फिर बाद में स्तर 4 के साथ।
छोटी गाड़ी के निष्पादन में, पिछले संकलन समाप्त हो गए हैं ( made non entrant
) और इसे फिर से 3 स्तर पर संकलित किया गया है (जो कि C1
, पिछले लिंक को देखें)।
तो यह निश्चित रूप से एक बग है C2
, हालांकि मुझे पूरी तरह से यकीन नहीं है कि क्या तथ्य यह है कि यह स्तर 3 संकलन पर वापस जा रहा है, इसे प्रभावित करता है (और क्यों यह स्तर 3 पर वापस जा रहा है, इसलिए अभी भी कई अनिश्चितताएं हैं)।
आप खरगोश छेद में और भी गहराई तक जाने के लिए निम्नलिखित कोड के साथ विधानसभा कोड उत्पन्न कर सकते हैं ( विधानसभा मुद्रण को सक्षम करने के लिए यह भी देखें )।
java -XX:+PrintCompilation -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly LoopOutPut > broken.asm
इस बिंदु पर, मैं कौशल से बाहर निकलने के लिए शुरू कर रहा हूं, पिछले संकलित संस्करणों को छोड़ दिए जाने पर छोटी गाड़ी का व्यवहार प्रदर्शित होना शुरू हो जाता है, लेकिन मेरे पास जो थोड़ा सा विधानसभा कौशल है वह 90 के दशक का है, इसलिए मैं किसी को मेरे मुकाबले इसे ले जाने की अनुमति देता हूं। यहां से।
यह संभावना है कि इस बारे में पहले से ही एक बग रिपोर्ट है, क्योंकि किसी और के द्वारा ओपी को कोड प्रस्तुत किया गया था, और जैसा कि सभी कोड सी 2 बग के साथ नहीं है । मुझे आशा है कि यह विश्लेषण दूसरों के लिए उतना ही जानकारीपूर्ण रहा होगा जितना कि यह मेरे लिए था।
जैसा कि आदरणीय अपांगिन ने टिप्पणियों में बताया, यह एक हालिया बग है । सभी इच्छुक और सहायक लोगों के लिए बहुत कुछ है :)