java - आउटपुट-1 लूप में स्लैश बन जाता है




string while-loop (2)

आश्चर्यजनक रूप से, निम्न कोड आउटपुट:

/
-1

कोड:

public class LoopOutPut {

    public static void main(String[] args) {
        LoopOutPut loopOutPut = new LoopOutPut();
        for (int i = 0; i < 30000; i++) {
            loopOutPut.test();
        }

    }

    public void test() {
        int i = 8;
        while ((i -= 3) > 0) ;
        String value = i + "";
        if (!value.equals("-1")) {
            System.out.println(value);
            System.out.println(i);
        }
    }

}

मैंने यह निर्धारित करने के लिए कई बार कोशिश की कि यह कितनी बार होगा, लेकिन, दुर्भाग्य से, यह अंततः अनिश्चित था, और मैंने पाया कि -2 का आउटपुट कभी-कभी एक अवधि में बदल जाता है। इसके अलावा, मैंने बिना किसी परेशानी के लूप और आउटपुट -1 को हटाने की भी कोशिश की। मुझे कौन बता सकता है क्यों?

JDK संस्करण की जानकारी:

HopSpot 64-Bit 1.8.0.171
IDEA 2019.1.1

पता नहीं क्यों जावा इस तरह के यादृच्छिक उत्पादन दे रहा है, लेकिन यह मुद्दा आपके सहमति में है जो लूप के for i बड़े मूल्यों के लिए विफल रहता है।

यदि आप String value = i + ""; प्रतिस्थापित करते हैं String value = i + ""; String value = String.valueOf(i) ; साथ लाइन String value = String.valueOf(i) ; आपका कोड उम्मीद के मुताबिक काम करता है।

रूढ़िवादिता का उपयोग + स्ट्रिंग को इंट में बदलने के लिए देशी है और छोटी गाड़ी हो सकती है (अजीब तरह से हम इसे अब शायद मिल रहे हैं) और इस तरह के मुद्दे का कारण बन सकते हैं।

नोट: मैंने लूप के लिए i के मूल्य को 10000 तक कम कर दिया है और मुझे समस्या का सामना नहीं करना पड़ा।

इस मुद्दे को जावा हितधारकों को सूचित किया जाना चाहिए और वे उसी पर अपनी राय दे सकते हैं।

संपादित करें मैंने लूप के लिए i का मान 3 मिलियन में अपडेट किया और नीचे के रूप में त्रुटियों का एक नया सेट देखा:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.lang.Integer.getChars(Integer.java:463)
    at java.lang.Integer.toString(Integer.java:402)
    at java.lang.String.valueOf(String.java:3099)
    at solving.LoopOutPut.test(LoopOutPut.java:16)
    at solving.LoopOutPut.main(LoopOutPut.java:8)

मेरा जावा संस्करण 8 है।


यह openjdk version "1.8.0_222" (मेरे विश्लेषण में उपयोग किया गया), OpenJDK 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() संकलन करते हैं। एक बार शुरुआत में, और एक बार फिर बाद में (संभवतः क्योंकि जेआईटी ने नोटिस किया कि विधि कितनी गर्म है)। बग्गी निष्पादन test() में 5 बार संकलित (या विघटित) किया जाता है।

इसके अतिरिक्त, -XX:-TieredCompilation साथ -XX:-TieredCompilation (जो या तो व्याख्या करता है, या C2 का उपयोग करता है) या -Xbatch (जो मुख्य भाग में समानांतर रूप से चलने के बजाय संकलन को -Xbatch करता है), आउटपुट की गारंटी है और 30000 पुनरावृत्तियों के साथ प्रिंट आउट बहुत सारा सामान, इसलिए C2 संकलक अपराधी लगता है। यह -XX:TieredStopAtLevel=1 साथ चलने की पुष्टि करता है, जो C2 को निष्क्रिय करता है और आउटपुट नहीं देता है (स्तर 4 पर रोकना फिर से बग दिखाता है)।

सही निष्पादन में, विधि पहले स्तर 3 संकलन के साथ संकलित की जाती है, फिर बाद में स्तर 4 के साथ।

छोटी गाड़ी के निष्पादन में, पिछले संकलनों को विरूपित किया जाता है ( made non entrant ) और इसे फिर से लेवल 3 पर संकलित किया जाता है (जो कि C1 , पिछला लिंक देखें)।

तो यह निश्चित रूप से C2 में एक बग है, हालांकि मुझे पूरी तरह से यकीन नहीं है कि क्या तथ्य यह है कि यह स्तर 3 संकलन पर वापस जा रहा है, इसे प्रभावित करता है (और यह स्तर 3 पर वापस क्यों जा रहा है, अभी भी कई अनिश्चितताएं हैं)।

आप खरगोश छेद में और भी गहराई तक जाने के लिए निम्न कोड के साथ असेंबली कोड उत्पन्न कर सकते हैं (असेंबली प्रिंटिंग को सक्षम करने के लिए this भी देखें)।

java -XX:+PrintCompilation -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly LoopOutPut > broken.asm

इस बिंदु पर, मैं कौशल से बाहर निकलने के लिए शुरू कर रहा हूं, पिछले संकलित संस्करणों को छोड़ने पर छोटी गाड़ी का व्यवहार प्रदर्शित होना शुरू हो जाता है, लेकिन मेरे पास जो थोड़ा सा विधानसभा कौशल है वह 90 के दशक का है, इसलिए मैं apangin पकड़ पाने की कोशिश apangin क्योंकि वह उन लोगों में से एक हो सकता है जो जानता है कि क्या हो रहा है।

यह संभावना है कि इस बारे में पहले से ही एक बग रिपोर्ट है, क्योंकि किसी और के द्वारा ओपी को कोड प्रस्तुत किया गया था, और जैसा कि सभी कोड सी 2 बग के बिना नहीं है (यह भी इस से संबंधित हो सकता है)। मुझे आशा है कि यह विश्लेषण दूसरों के लिए उतना ही जानकारीपूर्ण रहा होगा जितना कि यह मेरे लिए था।

जैसा कि आदरणीय अपांगिन ने टिप्पणियों में बताया, यह एक हालिया बग है । सभी इच्छुक और सहायक लोगों के लिए बहुत कुछ है :)







jit