Java bytecode 분석 |
http://arhipov.blogspot.kr/2011/01/java-bytecode-fundamentals.html
https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
-
javap 는 java class file disassembler 이다.
bytecode 는 위 javap 명령을 통해 볼 수 있다.
-
public class Foo { private String bar; public String getBar(){ return bar; } public void setBar(String bar) { this.bar = bar; } }
위 코드의 bytecode 는 아래와 같다.
public class Foo extends java.lang.Object {
public Foo();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public java.lang.String getBar();
Code:
0: aload_0
1: getfield #2; //Field bar:Ljava/lang/String;
4: areturn
public void setBar(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #2; //Field bar:Ljava/lang/String;
5: return
}
-
aload_0 등에 사용되는 a prefix 는 object 를 handling 하는 opcode 라는 의미.
istore_2 와 같은 i prefix 는 integer 를 다루는 opcode 라는 의미.
-
#1. #2 과 같은 녀석은 constant pool 을 참조한다.
javap -c -s -verbose 를 수행하면 constant pool 도 볼 수 있다. ( -s 는 signatures, -verbose 는 detail )
-
aload_0 등과 같이 opcode 끝에 있는 _0 은 frame 안에 있는 instruction 위치를 나타낸다.
aload_0 은 stack 의 local variable table 0 position 에 value 를 넣는다는 의미이다.
constructor 나 instance method 는 항상 0 position 에 추가한다.
-
public class Example { public int plus(int a){ int b = 1; return a + b; } }
위 코드는 아래와 같은 bytecode 가 된다.
public int plus(int);
Code:
Stack=2, Locals=3, Args_size=2
0: iconst_1
1: istore_2
2: iload_1
3: iload_2
4: iadd
5: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this LExample;
0 6 1 a I
2 4 2 b I
-
public class ExceptionExample { public void foo(){ try { tryMethod(); } catch (Exception e) { catchMethod(); }finally{ finallyMethod(); } } private void tryMethod() throws Exception{} private void catchMethod() {} private void finallyMethod(){} }
위 코드는 아래와 같은 bytecode 가 된다.
public void foo();
Code:
0: aload_0
1: invokespecial #2; //Method tryMethod:()V
4: aload_0
5: invokespecial #3; //Method finallyMethod:()V
8: goto 30
11: astore_1
12: aload_0
13: invokespecial #5; //Method catchMethod:()V
16: aload_0
17: invokespecial #3; //Method finallyMethod:()V
20: goto 30
23: astore_2
24: aload_0
25: invokespecial #3; //Method finallyMethod:()V
28: aload_2
29: athrow
30: return
Exception table:
from to target type
0 4 11 Class java/lang/Exception
0 4 23 any
11 16 23 any
23 24 23 any
-
instruction list 는 아래와 같다.
aaload : array 의 한 값을 stack 에 올리기
aastore : array 의 한 값에 저장하기
aconst_null : null reference 를 stack 에 올리기
aload : local variable 을 stack 에 올리기
aload_0 : local variable 0 에 있는 녀석을 stack 에 올리기
aload_1 : local variable 1 에 있는 녀석을 stack 에 올리기
…
anewarray : 전달받은 count 를 기준으로 array 생성
areturn : method 에서 reference return
arraylength : array length 받아오기
astore : local variable 에 저장하기
astore_0 : local variable 0 에 저장하기
astore_1 : local variable 1 에 저장하기
…
athrow : error 나 exception 던지기
baload : array 에서 index 에 해당하는 boolean 값 읽어오기
…
bipush : byte 를 integer value 로 stack 에 올리기
breakpoint : java debugger 를 위해 reserve 된 breakpoint. class file 에 나오면 안 된다.
caload : array 에서 index 에 해당하는 char 값 읽어오기
…
checkcast : 특정타입인지 검사
d2f : double 을 float 으로 변환
d2i : double 을 int 로 변환
d2l : double 을 long 로 변환
dadd : double 2개 더하기
daload : array 에서 index 에 해당하는 double 값 읽어오기
…
dcmpg : 두개의 double 비교
dcmpl : 두개의 double 비교 ( 위와 차이가 뭐지? )
dconst_0 : double 0.0 을 stack 에 올리기
dconst_1 : double 1.0 을 stack 에 올리기
ddiv : 두개의 double 나누기
dload : double value 를 stack 에 올리기
dload_0 : local variable 0 으로부터 double 읽어오기
…
dmul : 두개의 double 곱하기
dneg : double 을 negative 로
drem : 두개의 double 의 remainder
dreturn : method 에서 double return
dstore : double value 를 local variable 에 저장
dstore_0 : local variable 0 에 double 값 저장
…
dsub : double 두개의 차
dup : stack 의 top 에 있는 값을 복사한다.
…
dup2 : stack 의 top 에 있는 2개의 값을 복사한다.
…
getfield : objectref 로부터 field value 를 가져온다
getstatic : static field value 를 class 로부터 가져온다
goto : branchoffset 에 해당하는 instruction 으로 이동
goto_w : branchoffset 에 해당하는 instruction 으로 이동
i2b : int 를 byte 로 변환
...
i2s : int 를 short 로 변환
iand : 2개의 int 에 대해 bitwise operation 수행
..
iconst_m1 : int -1 을 stack 에 올림
…
if_acmpeq : 2개의 reference value 를 받아 equal 이면 instruction 이동
if_acmpne : 2개의 reference value 를 받아 not equal 이면 instruction 이동
if_i_cmpeq : 2개의 int 를 받아 equal 이면 instruction 이동
if_i_cmpge : 2개의 int 를 받아 greater than or equal 이면 instruction 이동
if_i_cmpgt : 2개의 int 을 받아 greater 이면 instruction 이동
if_i_cmple : 2개의 int 을 받아 less than or equal 이면 instruction 이동
if_i_cmplt : 2개의 int 을 받아 less than 이면 instruction 이동
if_i_cmpne : 2개의 int 을 받아 not equal 이면 instruction 이동
ifeq : value 가 0 이면 instruction 이동
ifge : value 가 0보다 크거가 같으면 instruction 이동
ifle : value 가 0보다 작거나 같으면 instruction 이동
iflt : value 가 0보다 작으면 instruction 이동
ifne : value 가 0 과 같지 않으면 instruction 이동
ifnonnull : value 가 not null 이면 instruction 이동
ifnull : value 가 null 이면 instruction 이동
iinc : local variable increment
…
impdep1 : debugger 에서 사용하는 에약된 op. class file 에 나타나면 안된다.
impdep2 : 상동
instanceof : type 확인
invokedynamic : dynamic method 를 수행하고 결과를 stack 에 올린다.
invokeinterface : interface method 를 호출하고 결과를 stack 에 올린다.
invokespecial : instance method 를 호출하고 결과를 stack 에 올린다.
invokestatic : static method 를 호출하고 결과를 stack 에 올린다.
invokevirtual : virtual method 를 호출하고 결과를 stack 에 올린다.
ior : int 에 대한 bitwise op
ishl : int shift left
ishr : int shift right
...
iushr : int unsigned shift right
ixor : int xor
jsr : jump to subroutine
jsr_w : jump to subroutine
…
lcmp : 2개의 long 비교값을 -1, 0, 1 기준으로 올림
…
ldc : constant pool 에서부터 #index 에 해당하는 constant 를 가져와 올림
…
lookupswitch : key 를 이용해 table 로부터 target address 를 찾아서, 그곳에서부터 instruction 수행
…
monitorenter : object 에 대한 monitor 들어감 (synchronized() section)
monitorexit : object 에 대한 monitor 해제
multianewarray : 다차원 배열 생성
new : 새로운 object 생성
newarray : 새로운 array 를 count 사이즈로 생성
nop : no op
pop : stack 의 top value 제거
pop2 : stack 의 top 2개 value 제거
putfield : value setting
putstatic : static value setting
ret : local variable 로부터 받은 주소로부터 코드 계속 실행
return : return
sipush : short 를 integer value 로 해서 stack 에 올림
swap : stack 의 top 2개의 word 를 swap
tableswitch : table 의 전달된 index 위치에 해당하는 곳으로부터 실행 계속
wide : opcode 를 수행
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[Java8 In Action] #1 기초 (2) | 2018.12.21 |
---|---|
[Java] Semaphore 에 대해 알아보자. (0) | 2018.12.20 |
[android] AutoFill Service 란 녀석이 나타났다. (0) | 2018.12.09 |
[android] Robolectric tutorial (0) | 2018.12.08 |
[android] Mockito 맛보기 ( test library ) (2) | 2018.12.07 |
댓글