본문 바로가기
프로그래밍 놀이터/안드로이드, Java

Java bytecode 분석

by 돼지왕 왕돼지 2018. 12. 19.
반응형

Java bytecode 분석


http://arhipov.blogspot.kr/2011/01/java-bytecode-fundamentals.html

https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings


a prefix, aload_0, alod_1, areturn, bytecode, constant pool, constant pool command, getField, i prefix, init, instruction list, invokespecial, istore_2, Java bytecode 분석, java class file disassembler, javap, javap -c -s -verbose, opcode, putfield, Signature, verbose


-

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 를 수행




반응형

댓글