Java Class File Format

Post on 19-Jan-2015

337 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Java Class File Format 세미나 자료

Transcript

JAVA CHOBO STUDY SEMINAR2013. 12.

Eminency

http://cafe.naver.com/javachobostudy

CONTENTS 1. What is ‘Format’2. Bytecode Concept3. Compile4. Class File Format

WHAT IS ‘FORMAT’

BYTES 컴퓨터에서 처리되는 모든 것은 byte 의 흐름(Stream)

(File)0x03, 0x22, 0x00, 0x3a, …

(Memory)0xff, 0xdf, 0x32, 0x4a, …

(Network Data)0x9d, 0x34, 0x05, 0x80, …

그럼 어떤 데이터를 어떻게 구분해서 사용할 수 있지 ?

-> 미리 약속된 DATA FORMAT 에 따라 입출력하게 됨 (NETWORK 의

경우 프로토콜이라고 불림 )

FILE FORMAT • 8 byte 짜리 파일 “ what.dat”

“0x04, 0x68, 0x9f, 0x6f, 0x79, 0x0a, 0xc8, 0x55”

• Format 을 모르면 무용지물• short(2), int(4), byte(1), byte(1) 일

수도• Double(8) 일 수도• 단지 String 일 수도 있음 (text file)

• 기본적으로 문자 코드 (Ascii code, UTF-8, EUC-KR, …) 로만 이루어져 있으면 텍스트 파일 , 그 외에는 바이너리 파일이라고 보면 됨 .

• 에디터에서 잘 보이면 텍스트 파일 -_-

FILE FORMAT • 확장자로 파일을 구분하는 것은 ‘사람’을 위한 것

• 누가 야동 파일 확장자를 avi 에서 hwp 로 바꿔 놓으면 어떻게 암 ?

• 군대에서 영창 갈 뻔…

• 리눅스 / 유닉스에서는 ( 주로 알려진 ) 파일 포맷을 검사하는 file 이란 툴 존재

* JAVA 에서 바이너리 데이터 읽기

• 파일이든 네트웍이든 DataInputStream 쓰면 다 된다 -_-

• 예• readShort() : 2 바이트 읽어서 short

로 리턴해 줌• readInt() : 4 바이트 읽어서 int 로

리턴해 줌

BYTECODE CONCEPT

ASSEMBLY • 컴퓨터는 기계어를 이해한다 .• 기계어를 처리하는 것은 CPU 다 .• CPU 는 (32 비트 기준 ) 극단적으로 말해

스위치 32 개를 가진 회로이다 .• 즉 이 32 개의 스위치 -> 32 개의 비트 (4

바이트 ) 를 어떤 방식으로 켜고 끄느냐에 따라 CPU 가 하는 일이 달라진다 .

ASSEMBLY • 즉 CPU 는 순서대로 들어오는 기계어 명령을 곧이 곧대로 처리할 뿐 , 변수니 함수니 메써드니 클래스니 하는 개념 따위는 전혀 없다 .

• 예 : 2+3 을 실행하면 컴퓨터는 다음과 같이 처리함

1. Stack 에 2 저장 .2. Stack 에 3 저장 .3. Stack 에서 숫자 두 개 빼서 더한 후 결과를

다시 stack 에 저장4. Stack 에서 pop -> 결과는 5

BYTECODE • JVM Bytecode 도 실행 원리는 어셈블리와 동일 .

• Bytecode 와 stack 과 ‘정해진 갯수’의 임시 변수만 갖고 모두 처리

• 우리가 쓰는 Java Code 는 ‘사람이 보기 편한’ 형태일 뿐 . 사실은 한 마디로 말해서 C 든 Java 든 죄다 컴퓨터가 이해 못하는 언어임 .

WHY BYTECODE?

• ( 복잡해 보이겠지만 ) 구현이 간단함 .• CPU 가 처리하는 어셈블리 코드랑 형태가

비슷

• 계산기를 프로그래밍한다고 생각해 보면 ,

• 예 : 3+4*2-1• 한 번에 계산식을 읽으면서 중간중간

계산 해서 최종 결과를 내는 방식도 있겠지만

• 계산식이 복잡해질 수록• 4*2 -> (a)• 3 + (a) -> (b)• (b) – 1

• 이런 식으로 작은 수식으로 분해 ( 혹은 트리구조 분해 ) 해서 각각의 계산을 처리하는 방식이 훨씬 용이

• 처음 식이 Java code 라면 작은 수식들이 바이트코드인 셈

COMPILE PROCESS

COMPILE? • Source code 를 기계어 파일 – 실행파일이나 라이브러리로 번역하는 과정

• 컴파일의 과정• Tokenizing• Syntax parsing• Optimization• Code Generation

TOKENIZING • 언어에 정의된 각각의 토큰을 체크하는 과정

• if ( a >= 1) continue;->• IF, LP, STR, GTR, NUM, RP,

CONTINUE, SEMICOL

PARSING • 각 토큰들이 문법에 맞게 제대로 배치되었는지 확인

• IF, LP, STR, GTR, NUM, RP, CONTINUE, SEMICOL

• 예 )• if 다음엔 반드시 왼쪽 괄호가 오므로

LP 가 아닌 경우 에러• >= 다음엔 숫자 외에도 변수 , 메써드

등이 올 수 있으므로 NUM 이 아닌 경우에도 무조건 에러가 나오진 않음 . 하지만 바로 오른쪽 괄호가 온다면 에러

SYNTAX TREE

OPTIMIZATION • 말 그대로 코드 최적화

• 예 )• For 문 100 만번 도는데 안에 a=1

밖에 없다 . -> for 문 삭제• If (a > 0 && a > 1) -> 왼쪽 조건 삭제

• 이런 것들은 SQL 실행시에 DBMS 에서도 수행함

• 사람보다 낫다 -_-

CLASS FILE FORMAT

OVERALL FORMAT

Magic number(4)

Minor version(2)

Major version(2)

Constant pool

Access flags(2)

This class(2)

Super class(2)

Interface information

Field information

Method information

Attributes

• (n) = n bytes• 숫자가 없는 필드들은 사이즈 가변

적 , 즉 실제 코드와 비례해서 많아지는 데이터들

HEADER • Magic Number : class 파일임을 나타내는 특정 숫자 . 무조건 0xCAFEBABE 의 값을 가짐 .

• Major, Minor version : 클래스 파일 포맷 버전 .

• Constant pool : 문자열 상수 및 클래스 이름 , 메써드 이름 등의 정보를 가짐 .

• Access flags : 클래스 접근 권한• This class, super class : 현재 클래스와

부모 클래스 이름 및 정보 . Constant pool의 인덱스 번호임

ACCESS FLAGS

• 예• 1025 -> 0x0401-> 0x0400 | 0x0001-> public abstract class

값 의미0x0001 public

0x0010 final

0x0020 super

0x0200 interface

0x0400 abstract

JAVA TYPE SIGNITURE

Signature Type

B byte

C char

D double

F float

I int

J long

L<class name>; class

S short

Z boolean

[ array

Method 의 타입을 표현할 때 이 signature 를 써서 ‘ ( 인자들 ) 리턴형’ 형태로 사용함

SIGNATURE EXAMPLE

double divide(int i, int j)

-> (II)D

Object mymethod(int i, double d, Thread t)

-> (IDLjava/lang/Thread;)Ljava/lang/Object;

CONSTANT POOL

Constant Pool Count(2)

Constant Info #1

Constant Info #2

Constant Info #n

전체 POOL 구성

각 Constant Info 구성tag(1)

(constant type 표시 )

data(tag 에 따라 사이즈 다름 )

CONSTANT TAGType Value

CONSTANT_Class 7

CONSTANT_Fieldref 9

CONSTANT_Methodref 10

CONSTANT_InterfaceMethodref 11

CONSTANT_String 8

CONSTANT_Integer 3

CONSTANT_Float 4

CONSTANT_Long 5

CONSTANT_Double 6

CONSTANT_NameAndType 12

CONSTANT_Utf8 1

각각의 자세한 정보는 JVM specification 참고

CONSTANT INFO

• 하지만 그냥 넘어가면 서운하니 몇 가지만…

tag(1)

class index(2) -> CP

Name and type index(2) -> CP

CONSTANT_Methodref_Info

tag(1)

name index(2) -> CP

CONSTANT_Class_Info

tag(1)

length(2)

Utf8 string (length)

CONSTANT_Utf8_Info

CONSTANT INFO EXAMPLE

1) #35 의 tag 10 은 MethodRef 이며 1 은 Class 인덱스 , 36 은 Name and Type 의 인덱스

2) #1 의 tag 는 ClassInfo 이며 index 2 값은 클래스 이름을 가리킴

3) #36 은 NameAndType 이며 이름 인덱스가 37, 타입 인덱스가 22.

index tag Index1(or value)

index2

#1 7 2

#2 1 my/test/Test

#22 1 (II)I

#35 10 1 36

#36 12 37 22

#37 1 add

시작 ->

4) #37 은 ‘ add’ 이며 #22 는 ‘ (II)I’5) 그러므로 #35 가 가리키는 메써드는

my.test.Test 클래스에 속한 int add(int i1, int i2) 임을 알 수 있음 .

* 파라미터의 변수 이름은 현재 단계에서는 알 수 없으나 클래스 파일의 메써드 정보에서 Local Variables 정보로 확인 가능

CONSTANT IFNO • 복잡해 보이지만 파일 사이즈를 줄이려면 최대한 중복을 줄여야 하니 어쩔 수 없음 .

• Database 설계 및 사용시 중복 데이터를 줄이기 위해 정규화를 하고 각종 테이블로 나눠놓고 또 복잡하게 foreign key 참조해서 join 해서 불러다 쓰고 하는 걸 경험해 본 분들도 계실텐데 결국 같은 사상을 깔고 있는 것임 .

THIS CLASS, SUPER CLASS

• 각 2 바이트를 차지하는 것에서 유추 가능하듯 , 이 부분은 따로 정보를 갖고 있는게 아니라 각각 Constant Info 의 해당 Class Info 번호를 가리킴

INTERFACE INFO

• 이 클래스가 구현하는 인터페이스 정보들

• 첫번째 2 바이트는 인터페이스 갯수를 의미하며 , count 수만큼 각 2 바이트의 인터페이스 정보를 가리키는 constant pool 인덱스가 있다 .

• 즉 , this class, super class 와 같은 방식 .

Interface Count(2)

Interface Info #1 (2)

Interface Info #2 (2)

Interface Info #n (2)

FIELD INFO

• 클래스가 갖고 있는 필드 –인스턴트 변수 및 클래스 변수 - 에 대한 정보 .

Field Count(2)

Field Info #1

Field Info #2

Field Info #n

Access flags(2)

Name index(2) -> CP

Descriptor index(2) -> CP

Attribute count(2)

Attributes[count]

Field Info 전체 구성

각 Field Info 구성

ACCESS FLAGS

• 예• 25-> 0x0019-> 0x0010 | 0x0008 | 0x0001-> public static final 변수

값 의미0x0001 public

0x0002 private

0x0004 protected

0x0008 static

0x0010 final

0x0040 volatile

0x0080 transient

METHOD INFO

• 클래스가 갖고 있는 인스턴트 메써드 및 클래스 메써드에 대한 정보 .

• 필드 정보와 구성 동일

Method Count(2)

Method Info #1

Method Info #2

Method Info #n

Access flags(2)

Name index(2) -> CP

Descriptor index(2) -> CP

Attribute count(2)

Attributes[count]

Method Info 전체 구성

각 Method Info 구성

ACCESS FLAGS 값 의미0x0001 public

0x0002 private

0x0004 protected

0x0008 static

0x0010 final

0x0020 synchronized

0x0100 native

0x0400 abstract

0x0800 strictfp

ATTRIBUTE• 클래스 , 메써드 , 필드의 기본 정보

( 접근 권한 , 타입 등 ) 이외에 추가적인 속성에 대한 정보가 기록됨

• 속성이 속성을 또 가질 수 있음 .

• 속성이란 단어를 쓰지만 필수적인 정보들도 있음

- 예를 들어 메써드 같은 경우는 Code 란 속성이 필수적이며 Code 는 LineNumberTable, LocalVariableTable 에 대한 속성이 있음 .

ATTRIBUTE

Attribute Name Index (2)

Attribute Length (4)

Attribute Data

Attribute Name 에 따라 Data 구성은 다름

종류 (Name) 의미ConstantValue 상수값

Code 메써드의 바이트코드Exceptions 예외들

InnerClasses 내부 클래스Synthetic

SourceFile 소스 파일 정보LineNumberTable 바이트 코드와

매칭되는 실제 소스 코드 라인번호

LocalVariableTable 지역변수 정보Deprecated

CODE ATTRIBUTE

Name index(2)

Attribute Length(4)

Max Stack(2)

Max Local(2)

Code Length(4)

Code

Exception Table

Attributes

METHOD DECOMPILE EXAMPLE

Method Info

Access flags : public

Name : minus

Type : (II)I

Max stack : 2

Max local : 3

Code:0x1B0x1C0x640xAC

LocalVariableTable

Start PC

Length Name Type Index

0 4 this Lmy/test/Test; 0

0 4 a I 1

0 4 b I 2

LineNumberTable

Start PC

Line

0 7

METHOD DECOMPILE EXAMPLE(CODE 설명 )

• 0x1B (iload_1) -> local 변수 1 을 스택에 로드

• 0x1C (iload_2) -> local 변수 2 를 스택에 로드

• 0x64 (isub) -> stack 에서 두 개의 아이템을 꺼내 뺄셈하고 결과를 다시 stack 에 넣음

• 0xAC (ireturn) -> stack 의 아이템을 메써드 결과값으로 리턴

METHOD DECOMPILE EXAMPLE

#1

• 0x1B (iload_1) -> local 변수 1 을 스택에 로드

변수 1 은 LocalVariableTable 에 따라 int a

STACK

a

METHOD DECOMPILE EXAMPLE

#2

• 0x1C (iload_2) -> local 변수 2 를 스택에 로드

변수 2 는 LocalVariableTable 에 따라 int b

STACK

ba

METHOD DECOMPILE EXAMPLE

#3

• 0x64 (isub) -> stack 에서 두 개의 아이템을 꺼내 뺄셈하고 결과를 다시 stack 에 넣음

STACK

ba

a - b

METHOD DECOMPILE EXAMPLE

#4

• 0xAC (ireturn) -> stack 의 아이템을 메써드 결과값으로 리턴

STACK

a - b

return

METHOD DECOMPILE EXAMPLE

#5

• 메써드 정보에서 이 메써드의 이름이나 타입을 모두 알 수 있음 .

• 메써드 signature 와 LocalVariableTable 를 비교해서 인자 변수 이름도 모두 파악 가능

• LineNumberTable 과 대조해 보면 한 줄짜리 메써드라는 것이 파악됨 .

결과 ) my.test.Test 클래스 안의 7 번째 라인의 minus 메써드 .

public int minus(int a, int b) { return a-b;}

REFERENCES• Java VM spec : http://goo.gl/52JCW

• Wikipedia Bytecode Instruction : http://goo.gl/pncN9

• Demo Code : https://code.google.com/p/javaseminar/

top related