Java 프로그램의 실행 과정
- 소스 코드 작성
- 컴파일러(javac)는 자바 소스코드(.java)를 JVM이 해석할 수 있는 바이트 코드(.class)로 변환
- JVM은 클래스 파일의 바이트 코드를 해석하여 바이너리 코드로 번역하고 연산을 처리
MyProgram.java
public class MyProgram {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
MyProgram.class
# 아래 컴파일 명령을 통해 MyProgram.class 파일이 생성된다.
javac MyProgram.java
# 32bit 기반의 헥사코드로 나타낸 바이트 코드
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
00000000 CA FE BA BE 00 00 00 3D 00 1D 0A 00 02 00 03 07 00 04 0C 00 05 00 06 01 00 10 6A 61 76 61 2F 6C
00000020 61 6E 67 2F 4F 62 6A 65 63 74 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 09 00 08 00 09 07 00
00000040 OA OC 00 OB 00 0C 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 74 01
00000060 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 3B 08 00 0E 01 00 0C 48 65 6C
00000080 6C 6F 20 57 6F 72 6C 64 21 0A 00 10 00 11 07 00 12 0C 00 13 00 14 01 00 13 6A 61 76 61 2F 69 6F
000000A0 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 76 61 2F
000000С0 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 07 00 16 01 00 09 4D 79 50 72 6F 67 72 61 6D 01 00 04
000000E0 43 6F 64 65 01 00 OF 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 01 00 04 6D 61 69 6E 01 00 16
00000100 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 01 00 0A 53 6F 75 72 63 65 46
00000120 69 6C 65 01 00 0E 4D 79 50 72 6F 67 72 61 6D 2E 6A 61 76 61 00 21 00 15 00 02 00 00 00 00 00 02
00000140 00 01 00 05 00 06 00 01 00 17 00 00 00 1D 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 01 00
00000160 18 00 00 00 06 00 01 00 00 00 01 00 09 00 19 00 1A 00 01 00 17 00 00 00 25 00 02 00 01 00 00 00
00000180 09 B2 00 07 12 0D B6 00 OF B1 00 00 00 01 00 18 00 00 00 0A 00 02 00 00 00 03 00 08 00 04 00 01
000001A0 00 1B 00 00 00 02 00 1C
바이트 코드 자체는 JVM, 즉 머신이 이해하는 이진 파일이기 때문에 사람이 이해하는 것은 쉽지 않다.
따라서 바이트 코드를 사람이 이해할 수 있는 수준으로 보기 위해선 JDK에서 제공하는 javap를 통해 역어셈블 과정을 거쳐야 한다.
(IDE에서 제공하는 기능을 통해서도 확인 가능)
# .class 는 생략
# -v (--verbose) : 클래스 파일의 세부정보, 메서드 필드 접근제어자 상수 풀 등
# -p (--private) : private 멤버를 포함 (기본값은 public 멤버만)
# -s (--printstack) : 각 메소드별 스택 Map
# -sysinfo : 클래스 파일의 시스템 정보 (호환되는 JDK, 소스 파일 등)
# -constants : 상수 풀의 내용 출력
javap -v -p -s -sysinfo -constants MyProgram
Classfile ../src/main/java/MyProgram.class
Last modified 2023. 12. 11.; size 423 bytes
SHA-256 checksum ac29d9411946456e7baf7c18d0b26a38067016b38ff6a2443a8ac0f37b144485
Compiled from "MyProgram.java"
public class MyProgram
minor version: 0
major version: 61
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #21 // MyProgram
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5:#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Fieldref #8.#9 // java/lang/System.out:Ljava/io/PrintStream;
#8 = Class #10 // java/lang/System
#9 = NameAndType #11:#12 // out:Ljava/io/PrintStream;
#10 = Utf8 java/lang/System
#11 = Utf8 out
#12 = Utf8 Ljava/io/PrintStream;
#13 = String #14 // Hello World
#14 = Utf8 Hello World
#15 = Methodref #16.#17 // java/io/PrintStream.println:(Ljava/lang/String;)V
#16 = Class #18 // java/io/PrintStream
#17 = NameAndType #19:#20 // println:(Ljava/lang/String;)V
#18 = Utf8 java/io/PrintStream
#19 = Utf8 println
#20 = Utf8 (Ljava/lang/String;)V
#21 = Class #22 // MyProgram
#22 = Utf8 MyProgram
#23 = Utf8 Code
#24 = Utf8 LineNumberTable
#25 = Utf8 main
#26 = Utf8 ([Ljava/lang/String;)V
#27 = Utf8 SourceFile
#28 = Utf8 MyProgram.java
{
public MyProgram();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String Hello World
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 4: 0
line 5: 8
}
실행
java MyProgram # Hello World!
'Java' 카테고리의 다른 글
JVM 내부 구조 (2) - 런타임 데이터 영역 (1) | 2023.11.29 |
---|---|
JVM 내부 구조 (1) - 클래스 로더 (1) | 2023.11.27 |
JVM, JDK, JRK (0) | 2023.11.27 |