JavaRush /Java Blog /Random-KO /Java 바이트코드 소개
billybonce
레벨 29
Москва

Java 바이트코드 소개

Random-KO 그룹에 게시되었습니다
IntellijIDEA에는 JRE가 작성된 코드를 어떻게 그리고 궁극적으로 실행하는지 확인할 수 있는 바이트코드 표시라는 훌륭한 기능이 있습니다.(그러나 이는 읽기 쉽도록 컴파일러가 기계 바이트코드를 일부 해석한 것이기도 합니다.) 바이트 코드 표시 기능은 컴파일된 .class 파일을 분석합니다. 명령에 대한 설명은 Wikipedia 링크에서 찾을 수 있습니다 .

따라서 동일한 라인을 초기화하여 두 가지 버전의 기본 메소드에 대한 바이트코드를 구문 분석하고 왜 다른 결과가 나오는지 명확히 하려는 아이디어가 떠 올랐습니다. 옵션 1: (str1==str2를 비교하면 false가 됩니다.) 옵션 2 : (str3== str4 를 비교하면 public static void main(String[] args){ String str1 = new String("test"); String str2 = new String("test"); } true가 됩니다.) public static void main(String[] args){ String str3 = "test"; String str4 = "test"; } 첫 번째 옵션의 바이트 코드(대괄호 [] 안에는 명령이 실행된 후 스택 상태가 표시됩니다(오른쪽 스택 상단)). 두 번째 옵션의 바이트코드: 자세한 내용을 볼 수 있는 링크: 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 그러면 왜 한 경우에는 문자열이 같고 다른 경우에는 동일하지 않습니까? new String의 경우 문자열 상수 풀이 무시되고 문자열의 새 복사본이 생성되기 때문입니다(이에 대한 링크 src6). 바이트코드가 이를 명확히 하는 데 실제로 도움이 되지는 않았지만 두 번째 경우에는 더 적은 작업을 수행하므로 이 옵션이 더 낫다는 것은 분명합니다. 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 //количество локальных переменных метода



코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION