JavaRush /Blog Java /Random-MS /Pengenalan kepada kod bait Java
billybonce
Tahap
Москва

Pengenalan kepada kod bait Java

Diterbitkan dalam kumpulan
IntellijIDEA mempunyai ciri hebat - tunjukkan bytecode, yang membolehkan anda melihat bagaimana dan akhirnya JRE akan melaksanakan kod bertulis. (Walau bagaimanapun, ini juga beberapa tafsiran kod bait mesin oleh pengkompil untuk memudahkan pembacaan) Ditemui dalam View-> Tunjukkan Kod Byte Apa yang dilakukannya - menganalisis fail .class - yang disusun. Penerangan tentang arahan boleh didapati di pautan Wikipedia .

Sehubungan itu, idea timbul untuk menghuraikan kod bait bagi dua versi kaedah utama dengan permulaan baris yang sama, dan cuba menjelaskan mengapa ia memberikan hasil yang berbeza: Pilihan 1: (jika kita membandingkan str1==str2, kita mendapat palsu) Pilihan 2 : (jika kita membandingkan str3== public static void main(String[] args){ String str1 = new String("test"); String str2 = new String("test"); } str4 , maka kita akan menjadi benar) public static void main(String[] args){ String str3 = "test"; String str4 = "test"; } Bytecode pilihan pertama (dalam kurungan segi empat sama [] akan ada keadaan timbunan selepas perintah itu dilaksanakan (atas timbunan di sebelah kanan)): Bytecode bagi pilihan kedua: Pautan untuk membaca lebih lanjut: 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 Jadi mengapa rentetan sama dalam satu kes dan bukan dalam yang lain? Kerana dalam kes String baharu, kolam pemalar rentetan diabaikan dan salinan rentetan baharu dibuat (pautan src6 tentang ini). Dan walaupun bytecode tidak benar-benar membantu menjelaskan ini, jelas bahawa dalam kes kedua ia melakukan operasi yang lebih sedikit, dan oleh itu pilihan ini lebih baik. 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 ) //- в стеке будет link на проинициализированную строку: [value_result_string] //Почему для инициализации String(String) нужно три аргумента в стеке: //1)link на входной аргумент 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 - инициализаций //(и если её не хватит - то всё вылетит с Howим-нибудь 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 (который компилятор дописывает за нас How успешный конец метода) L3 LOCALVARIABLE args [Ljava/lang/String; L0 L3 0 //список локальных переменных, под которые выделяется память LOCALVARIABLE str1 Ljava/lang/String; L1 L3 1 //например: L1(метка где записан code) L3(метка где описан тип an object и выделяется память) 1(локальный номер an object) LOCALVARIABLE str2 Ljava/lang/String; L2 L3 2 // MAXSTACK = 1 //максимальная глубина стека для метода MAXLOCALS = 3 //количество локальных переменных метода



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