2011년 7월 31일 일요일

dalvik의 method 호출 opcode와 java bytecode의 비교


 java specification에는 메소드 호출시에 사용하는 바이트코드가 나와있는데

크게 다음 4가지를 사용한다고 볼수 있다. 

1. invokestatic

2. invokespecial

3. invokevirtual

4. invokeinterface

이름에서 대략 유추할수 있겠지만 invokestatic은 static 접근자로 지정된 메소드를 호출할때 

사용된다. 


일반적으로 jvm에서는 메소드 호출시에 인자의 첫번째로 객체 자신인 this 객체를 

저장한다. 정적 메소드 ( static method )의 경우 이러한 this 객체를 위한 공간이 필요없기

때문에 바로 인자만 들어가게 되므로 별도의 바이트 코드 invokestatic이 필요하다.


invokespecial은 주로 <init> 즉 객체의 생성자 메소드를 호출하기 위해 사용되고 
super class 메소드의 구현 메소드를 호출하기 위해서도 사용된다.

invokeinterface는 인터페이스의 메소드를 호출하기 위해 사용되고 나머지 대부분의

메소드들은 invokevirtual로 호출한다. 이름에서 알수있듯이 invokevirtual은 

dynamic method를 위한 바이트 코드임을 알수 있다. 

( java7에서는 invokedynamic이라는 bytecode가 새로 추가된듯 하다. )


source/android/dalvik/vm/meterp/out/ 폴더에 보면 하드웨어별로 

dalvik의 opcode 구현이 들어있다. dalvik에서는 

invoke-virtual, invoke-virtual/range, invoke-virtual-quick, invoke-virtual-quick/range

invoke-super, invoke-super/range, invoke-super-quick, invoke-super-quick/range

invoke-direct, invoke-direct/range

invoke-static, invoke-static/range

등등 꽤 많다. 크게 보아 종류는 똑같이 4종류인데 invokespecial이 invoke-direct로 이름이

더 직관적으로 바뀐듯하고 바로 위 부모 클래스의 메소드를 호출하는 invoke-super가 생기고

invokeinterface에 대응되는 바이트코드는 제거되었다. 

(직접 확인해 봐야 겠지만 아마도 invoke-virtual이 이 역할까지 함께 할듯 하다.)


range 계열은 parameter에 range를 쓸수 있는데 예를 들어,

invoke-virtual {v1,v2,v3} 처럼 호출하는 것을 range 계열은 invoke-virtual/range {v1 … v3}

처럼 호출한다.

quick 계열은 parameter외에도 부모 클래스의 인스턴스 포인터를 위한 별도의 테이블을 사용한다. 

즉 invoke-virtual-quick {parameter}, vtable 과 같은 형식으로 사용된다.

cvm이나 kvm의 구현부에서는 invokevirtual 바이트코드의 실행시 부모 클래스의 주소로 

한단계식 따라가며  메소드를 호출하게 되는데 테이블에 미리 부모 클래스들의 주소를 

로드시켜 놓고 빠르게 호출하기 위한 용도로 quick 계열의 메소드를 사용하는 듯하다.

댓글 1개: