JavaRush /Java-Blog /Random-DE /Einführung in Java-Bytecodes
billybonce
Level 29
Москва

Einführung in Java-Bytecodes

Veröffentlicht in der Gruppe Random-DE
IntellijIDEA verfügt über eine wunderbare Funktion – Bytecode anzeigen, mit der Sie sehen können, wie und letztendlich die JRE den geschriebenen Code ausführt. (Dies ist jedoch auch eine Interpretation des Maschinenbytecodes durch den Compiler zur leichteren Lesbarkeit.) Zu finden in Ansicht-> Bytecode anzeigen Was es tut – analysiert kompilierte .class-Dateien. Beschreibungen der Befehle finden Sie unter dem Wikipedia- Link .

Dementsprechend entstand die Idee, die Bytecodes für zwei Versionen der Hauptmethode mit Initialisierung identischer Zeilen zu analysieren und zu klären, warum sie unterschiedliche Ergebnisse liefern: Option 1: (wenn wir str1==str2 vergleichen, erhalten wir false) Option 2 : (wenn wir str3== public static void main(String[] args){ String str1 = new String("test"); String str2 = new String("test"); } str4 vergleichen, dann erhalten wir true) public static void main(String[] args){ String str3 = "test"; String str4 = "test"; } Bytecode der ersten Option (in eckigen Klammern [] wird der Status des Stapels angezeigt, nachdem der Befehl ausgeführt wurde (oben im Stapel rechts)): Bytecode der zweiten Option: Links zum Weiterlesen: src1: http://cs.au.dk/~mis /dOvs/jvmspec/ref--33.html src2: http://mihaimoldovan.com/download/Inside- Java-Virtual-Machine.pdf src3: http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool src4: http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings src5: http://stackoverflow.com/questions /10209952/java-constant-pool src6: http://stackoverflow.com/questions/14150628/string-constant -pool-java Warum sind die Strings also in einem Fall gleich und im anderen nicht? Denn im Fall eines neuen Strings wird der String-Konstantenpool ignoriert und eine neue Kopie des Strings erstellt (Link src6 dazu). Und obwohl der Bytecode nicht wirklich zur Klärung beigetragen hat, ist es offensichtlich, dass er im zweiten Fall weniger Operationen ausführt und diese Option daher besser ist. public static main([Ljava/lang/String;)V L0 LINENUMBER 5 L0 NEW java/lang/String //новая строка - кладем ссылку на класс "String "на вершину стека: [value_string] DUP //копируем ссылку на вершине стека: [value_string, value_string] LDC "test" //кладём в стек ссылку на "test" из constant pool(а если в нём еще нет ссылки на "test", //то она также остается в constant pool'e): [value_string, value_string, value_test] INVOKESPECIAL java/lang/String. (Ljava/lang/String;)V //вызов new для String с аргументами с вершины стека - //после вызова инициализирующего метода для стринг(и его внутренних манипуляций со стеком, //которые аналогично можно посмотреть в ByteCodeе java.lang.String ) //- в стеке будет Verknüpfung на проинициализированную строку: [value_result_string] //Почему для инициализации String(String) нужно три аргумента в стеке: //1)Verknüpfung на входной аргумент 2)новая строка, 3)хешCode строки ASTORE 1 //сохраняем ссылку с вершины стека в локальную переменную(1) с вершины стека: [ ] L1 LINENUMBER 6 L1 NEW java/lang/String //аналогично первой строке DUP LDC "test" INVOKESPECIAL java/lang/String. (Ljava/lang/String;)V ASTORE 2 L2 LINENUMBER 7 L2 RETURN //return void - компилятор дописывает за нас если метод возвращает void L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 // список локальных переменных метода LOCALVARIABLE str3 Ljava/lang/String; L1 L3 1 // L1(метка где операции с локальной переменной) L3(метка где описание что это за локальная переменная) 1(номер локальной переменной) LOCALVARIABLE str4 Ljava/lang/String; L2 L3 2 // MAXSTACK = 3 //максимальная глубина стека метода MAXLOCALS = 3 //количество локальных переменных метода // //То есть сначала JRE будет выделять память при //вызове метода учитывая всю вложенность вызовов методов и new - инициализаций //(и если её не хватит - то всё вылетит с Wieим-нибудь OutOfMemory //эксепшном), а только потом будут производиться операции public static main([Ljava/lang/String;)V L0 LINENUMBER 5 L0 LDC "test" //берем ссылку на "test" из constant_pool и кладем на вершину стека: [value_test] ASTORE 1 //забираем ссылку с вершины стека в переменную(1) str1 : [ ] L1 LINENUMBER 6 L1 LDC "test" //берем ссылку на "test" из constant_pool и кладем на вершину стека: [value_test] ASTORE 2 //забираем ссылку с вершины стека в переменную(2) str2: [ ] L2 LINENUMBER 7 L2 RETURN //return void (который компилятор дописывает за нас Wie успешный конец метода) L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 //список локальных переменных, под которые выделяется память LOCALVARIABLE str1 Ljava/lang/String; L1 L3 1 //например: L1(метка где записан Code) L3(метка где описан тип ein Objektа и выделяется память) 1(локальный номер ein Objektа) LOCALVARIABLE str2 Ljava/lang/String; L2 L3 2 // MAXSTACK = 1 //максимальная глубина стека для метода MAXLOCALS = 3 //количество локальных переменных метода



Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION