JavaRush /Blog Java /Random-FR /Introduction aux bytecodes Java
billybonce
Niveau 29
Москва

Introduction aux bytecodes Java

Publié dans le groupe Random-FR
IntellijIDEA a une fonctionnalité merveilleuse : afficher le bytecode, qui vous permet de voir comment et finalement le JRE exécutera le code écrit. (Cependant, il s'agit également d'une interprétation du bytecode de la machine par le compilateur pour faciliter la lecture). Trouvé dans View-> Afficher le code d'octet Ce qu'il fait - analyse les fichiers .class compilés. Les descriptions des commandes peuvent être trouvées sur le lien Wikipédia .

En conséquence, l'idée est née d'analyser les bytecodes de deux versions de la méthode main avec initialisation de lignes identiques, et d'essayer de clarifier pourquoi elles donnent des résultats différents : Option 1 : (si l'on compare str1==str2, nous obtenons faux) Option 2 : (si on compare str3== public static void main(String[] args){ String str1 = new String("test"); String str2 = new String("test"); } str4 , alors on obtient true) public static void main(String[] args){ String str3 = "test"; String str4 = "test"; } Bytecode de la première option (entre crochets [] il y aura l'état de la pile après l'exécution de la commande (en haut de la pile à droite)) : Bytecode de la deuxième option : Liens pour en savoir plus : 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 Alors pourquoi les chaînes sont-elles égales dans un cas et pas dans l'autre ? Parce que dans le cas d'une nouvelle chaîne, le pool de constantes de chaîne est ignoré et une nouvelle copie de la chaîne est créée (lien src6 à ce sujet). Et bien que le bytecode n'ait pas vraiment aidé à clarifier cela, il est évident que dans le second cas, il effectue moins d'opérations, et donc cette option est meilleure. 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 //количество локальных переменных метода



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