์ฐ๋ฆฌ๋ ๋ง์ ์๊ฐ Java๋ฅผ ์ด์ฉํด์ ๋ค์ํ ์ํํธ์จ์ด๋ฅผ ๊ฐ๋ฐํ๋ฉด์ ๋ค์๋ ์๋ฆฌ๊ฐ ์๋ค.
Java๋ JVM ์ด ์๊ธฐ ๋๋ฌธ์ ํ๋ซํผ์ ์ข ์์ ์ด์ง ์๊ณ ์ด์์ฑ์ด ๋ฐ์ด๋๋ค.
๊ทธ ์ด์ ์ ๋ํด์ ์๊ฐํด๋ณธ ๊ฒฝํ์ด ์๋๊ฐ?
์ค๋์ ์์ JVM๊ณผ ์ด์์ฑ์ ์ดํดํ๊ธฐ ์ํด ๊ผญ ์์์ผ ํ๋ Java Bytecode ์ ๋ํด์ ์์๋ณด๋ ค ํ๋ค.
Java Bytecode, ์๋ฐ ๋ฐ์ดํธ์ฝ๋
์ฐ๋ฆฌ๋ Java ์ํํธ์จ์ด๋ฅผ ๊ฐ๋ฐํ๊ธฐ ์ํด์ JDK๋ฅผ ์ค์นํ๊ณ Java ์ํํธ์จ์ด๋ฅผ ์คํ์ํค๊ธฐ ์ํด์ JRE ๋ฅผ ์ค์นํ๋ค.
๋ํ ๊ฐ๋ฐ์ ํ๋ฉด ์คํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๊ธฐ ์ํด์ Compile ๊ณผ์ ์ ๊ฑฐ์น๊ฒ ๋๋๋ฐ, ์ด ์ปดํ์ผ์ ๋ฐ๋ก JDK๋ JRE ์ ํจ๊ป ํฌํจ๋๋ javac.exe
์คํํ์ผ์ด ์ํํ๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฐ๋ฐ์๊ฐ ์์ฑํ .java
ํ์ผ์ JVM์ด ์ดํดํ ์ ์๋๋ก ํ๋ Bytecode ๋ก ๋ณํํ๊ณ .class
ํ์ผ์ ๋ง๋๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ, .class
ํ์ผ์ ์กด์ฌํ๋ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋ก ์๋ฐ ๋ฐ์ดํธ์ฝ๋, Java Bytecode ์ธ ๊ฒ์ด๋ค.

์ฃผ์ํด์ผ ํ ์ ์ด ์ปดํ์ผ ๊ฒฐ๊ณผ ๋ผ๊ณ ํด์ C๋ C++์ด ์ปดํ์ผํ๋ฉด ์์ฑํ๋ ๊ธฐ๊ณ์ด์ ๋์ผํ๊ฒ ์๊ฐํ๋ฉด ์๋๋ค. ๊ธฐ๊ณ์ด๋ JVM์ด ๋ค๋ฅธ ๋ชจ๋์ ํตํด์ ์์ฑํ๊ณ ์คํํ๋๋ฐ, ์ด ๊ณผ์ ์์ C๋ C++์ ๋นํด ์กฐ๊ธ ๋๋ฆฐ ์ฑ๋ฅ์ ๋ด๋ ๊ฒ์ด๋ค.
Java Bytecode ๋ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ฐํ ์๋ฐ ํ๋ก๊ทธ๋จ(์ฝ๋)๋ฅผ ๋ฐฐํฌํ๋ ๊ฐ์ฅ ์์ ๋จ์๋ผ๊ณ ํ๋ค.
Java Bytecode ํ์ธํ๊ธฐ
๋ ๊น์ ์ดํด๋ฅผ ์ํด์ ์ฐ๋ฆฌ๊ฐ ์ง์ Java Bytecode ๋ฅผ ์์ฑํ๊ณ ํ์ธํด๋ณด์
๋ค์๊ณผ ๊ฐ์ java ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ๋ค.
public class Wonit {
public static void main(String[] args) {
String name = "์๋";
int age = 25;
Person blogger = new Person(name, age);
blogger.print();
}
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
void print() {
System.out.println("๋ธ๋ก๊ทธ ์ฃผ์ธ์ ์ด๋ฆ์ " + name + " ์ด๋ฉฐ ๋์ด๋ " + age + " ์ด๋ค");
}
}
์ด์ ์ด ์ฝ๋๋ฅผ ์ปดํ์ผํด๋ณด์.
IDE๋ฅผ ํตํด์ ์ปดํ์ผ์ ํด๋ ๋์ผํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ฒ ์ง๋ง ์ง๊ธ ๋งํผ์ javac.exe
๋ฅผ ์ด์ฉํด์ ์ง์ ์ปดํ์ผํด๋ณด์!
$ javac Wonit.java
$ ls
Wonit.java Wonit.class Person.class
ํ๋์ ํ์ผ์์ ์์ฑํ์ง๋ง ์ฐ๋ฆฌ๋ 2๊ฐ์ ํด๋์ค๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ์ปดํ์ผ๋๋ ์ฝ๋๋ 2๊ฐ์ ํด๋์ค ํ์ผ์ด ์์ฑ๋์๋ค.

๊ทธ๋ฆฌ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ HexD๋ Hex Viewer ๋ก ํ์ธํ๋ค๋ฉด Byte ํํ๋ก ์ง์ ํ์ธํ ์ ์์ง๋ง ์์ด ์ธ๋ ๊ฑฐ๋ฆฌ๋ฏ๋ก javap
๋ก ๋์ปดํ์ผ๋ง์ ํ๊ณ ๋ณด๊ธฐ ํธํ๊ฒ ๋ฐ๊ฟ๋ณด์.
$ javap -v -p -s Wonit.class
verbose ๋ฅผ ์ด์ฉํด์ ๋์ปดํ์ผ๋งํ๋ ๊ณผ์ ์ javap
๋ฅผ ์คํํ๋ฉด ๋๋ค.
๊ทธ๋ ด ๊ฒฐ๊ณผ๋ก ๋ค์๊ณผ ๊ฐ์ ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ฒ ๋๋ค.
minor version: 0
major version: 58
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #17 // Wonit
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
public class Wonit
minor version: 0
major version: 58
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
... ์๋ต
#24 = Utf8 Wonit.java
{
public Wonit();
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
Code:
stack=4, locals=4, args_size=1
0: ldc #7 // String ์๋
5: istore_2
... ์๋ต
20: return
LineNumberTable:
line 3: 0
line 4: 3
line 6: 6
line 8: 16
line 9: 20
}
SourceFile: "Wonit.java"
์ฌ์ค์ ์ด ์ฝ๋๋ค์ ์๋ฒฝํ๊ฒ ์ดํดํ๋ ๊ฒ์ ๋ด ์์ค์ผ๋ก ๋์ ํ ๋ถ๊ฐ๋ฅํ๋๋ผ.. ๊ทธ๋๋ ์ต๋ํ ์ดํดํ๋ ค๊ณ ํด๋ณด์๋๋ฐ, ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ด์ ํจ๊ป ๊ณต์ ํ๋ ค ํ๋ค.
Java Bytecode ์ ๊ตฌ์ฑ์์
์๋ฐ ๋ฐ์ดํธ์ฝ๋์ ๊ตฌ์ฑ์์๋ ๋ง์ด ์์ง๋ง ํฌ๊ฒ 3๊ฐ์ง๊ฐ ์กด์ฌํ๋ค๊ณ ๋ณด์
- Class Format
- Type์ ํํ
- Constant Pool
- Instruction Set
Class Format
์์ ์๋ฐ ๋ฐ์ดํธ์ฝ๋๋ ๋๋ฆ์ ํฌ๋งท์ด ์ ํด์ ธ์๊ณ , ํด๋น ํฌ๋งท์ผ๋ก ํํ์ด ๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ปดํ์ผํ ์ฝ๋๋
minor version: 0
major version: 58
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #17 // Wonit
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
์ ํด๋นํ๋๋ฐ, ์ด ํฌ๋งท์ ๋ค์๊ณผ ๊ฐ์ ํ์์ผ๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
- magic
- ํด๋์ค ํ์ผ์ ์ฒซ 4๋ฐ์ดํธ๋ก ์๋ฐ ํด๋์คํ์ผ์ด ๋ง๋์ง ๊ตฌ๋ถํ๋ ์ฉ๋๋ก ์ฐ์ธ๋ค. PE Header ๋ Image Signatur ๊ณผ ๊ฐ์ ์ฉ๋๋ผ๊ณ ๋ณด๊ณ
CAFEBABE
๋ผ๋ ์ด๋ฆ์ ๊ฐ๊ณ ์๋ค.
- ํด๋์ค ํ์ผ์ ์ฒซ 4๋ฐ์ดํธ๋ก ์๋ฐ ํด๋์คํ์ผ์ด ๋ง๋์ง ๊ตฌ๋ถํ๋ ์ฉ๋๋ก ์ฐ์ธ๋ค. PE Header ๋ Image Signatur ๊ณผ ๊ฐ์ ์ฉ๋๋ผ๊ณ ๋ณด๊ณ
- minor_version, major_version
- ํด๋์ค์ Version ์ ๋ํ๋ธ๋ค. ์ฆ, JDK 1.6์ด๋ 1.8์ด๋ ๋ฅผ ๊ตฌ๋ถํ๋๋ฐ, ๊ฐ๊ฐ JDK ๋ฒ์ ์ ๋ฐ๋ผ ๋ค๋ฅธ ์๊ฐ ๋์ค๊ฒ ๋๋ค
- constant_pool_count
- ํด๋์ค ํ์ผ์ ์์ ํ(Constant Pool) ์ ๊ฐฏ์๋ฅผ ๋ํ๋ด๋ ์ฉ๋๋ก ์ฌ์ฉ๋๋ค.
- access_flags
- ์ฃผ๋ก ํด๋์ค์
public
,final
๊ณผ ๊ฐ์ modifier ์ ๋ณด๋ฅผ ๋ํ๋ธ๋ค.
- ์ฃผ๋ก ํด๋์ค์
- interface_count
- ํด๋์ค๊ฐ ๊ตฌํํ ์ธํฐํ์ด์ค์ ๊ฐ์์ ๊ฐ ์ธํฐํ์ด์ค์ ๋ํ constant_pool ๋ด์ ์ธ๋ฑ์ค๋ฅผ ๋ํ๋ธ๋ค.
์์ ์ค๋ช ํ ํฌ๋งท ๋ง๊ณ ๋ ๋ค๋ฅธ ํฌ๋งท์ ์ ๋ณด๋ ๋ถ๋ช ์กด์ฌํ๊ฒ ์ง๋ง ์ด๋ค์ ์ค๋ช ํ๋ ๊ฒ์ ์คํ๋ ค ์ด ํฌ์คํ ์ ๋ชฉ์ ์ ์๋ ๊ฒ์ด๋ผ ํ๋จ์ด ๋์ด ์๋ตํ๋๋ก ํ๊ฒ ๋ค.
์ฌ์ค ๋ด๊ฐ ์ดํด๋ฅผ ํ์ง ๋ชปํ์๊ธฐ ๋๋ฌธ์
Type์ ํํ
์๋ฐ ๋ฐ์ดํธ์ฝ๋์ ํํ์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ Type ์ Bytecode Expression ์ผ๋ก ๋ณํํ ์ ์๋ค.
๋ํ์ ์ธ ํ์
์
B
: byteC
: charI
: intL<classname>;
: reference
์ ๋๊ฐ ์๋ค.
์๋ฅผ ๋ค์ด์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๊ฐ ์๋ค๋ฉด
Object print(String str, int i)
Type ์ ํํ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ํํํ ์ ์๋ค.
(java/lang/String;I)Ljava/lang/Object;
๋์ฑ ๊ตฌ์ฒด์ ์ธ ํ์ ์ ํํ์ oracle java bytecode docs๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
Chapter 4. The class File Format
The target of each jump and branch instruction (jsr, jsr_w, goto, goto_w, ifeq, ifne, ifle, iflt, ifge, ifgt, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmple, if_icmplt, if_icmpge, if_icmpgt, if_acmpeq, if_acmpne) must be the opcode of an instruction wi
docs.oracle.com
Constant Pool
JVM์ Host OS ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ต๋ํ ํจ์จ์ ์ผ๋ก ์ด์ฉํ๋๋ก ์ค๊ณ๊ฐ ๋์ด์๋ค.
์ด๋ฅผ ์ํด์ JVM์ Constant Pool ์ด๋ผ๋ ์ ๋ต์ ์ฌ์ฉํ๋๋ฐ, JVM์ด ๋์ ์ผ๋ก ์ฝ๋๋ฅผ ์คํ์ํฌ ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ฆ์ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ Constant Pool ์ ์ ์ฅํ๊ณ Constant Pool ์ ์กด์ฌํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ์ ์ ์ผ๋ก ๊ฐ์ ธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋์ฑ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
#
ํํ์ ํด์์ฝ๋๋ก ์์ํ๋ ๊ฒ์ด ํน์ง์ด๋ค.
์ด Constant Pool์ ๋ํด์๋ ํด๋น ๋ธ๋ก๊ทธ์ ์กฐ๊ธ ๋ ๊น์ Java - String Constant Pool ์์ ํ์ธํ ์ ์๋ค.
[์กฐ๊ธ ๋ ๊น์ Java] String ๊ณผ String Constant Pool
์ฐ๋ฆฌ๋ Java ๋ฅผ ์ฌ์ฉํ๋ฉด์ ์์ฃผ ๋ง์ String ์ Literal ์ ์ด์ฉํ๊ฒ ๋๋ค. ์ค๋์ ๊ทธ String์ด ์ด๋ค ํน์ฑ์ ๊ฐ์ก๋์ง ์กฐ๊ธ ๋ค๋ฅธ ๊ฐ๋์์ ๋ด๋ณด๋ ค ํ๋ค. String ์? String ์ Java ์์ ์ ๊ณตํ๋ ํน๋ณํ ์๋ฃ
wonit.tistory.com
Instruction Set
์๋ฐ ๋ฐ์ดํธ์ฝ๋๋ ์ปดํ์ผ๋ ๊ฒฐ๊ณผ๋ก ์์ฑ๋๋ ์ฝ๋ ์ด๋ฏ๋ก ์ผ์ข ์ ๋ช ๋ น์ด ์งํฉ์ด๋ผ๊ณ ํ ์ ์๋ค.
์ด๋ฅผ JVM Instruction Set ์ด๋ผ๊ณ ํ๋ค.
๋ช ๋ น์ด๋ ๋น์ฐํ๊ฒ OpCode์ Operands ๋ก ๊ตฌ์ฑ๋๋๋ฐ ์๋ฐ ๋ฐ์ดํธ์ฝ๋์์๋ 1 Byte์ OpCode์ 2 Byte์ Operands ๋ก ๊ตฌ์ฑ๋๋ค.
1 Byte์ OpCode ์ด๋ฏ๋ก ์ฌ์ฉ๊ฐ๋ฅํ ์ด ๋ช ๋ น์ด์ ์๋ 256๊ฐ๊ฐ ๋๊ณ ์์ธํ ๋ช ๋ น์ด์ ์ ์๋ Oracle Java Bytecode Instruction Set Docs ์์ ํ์ธํ ์ ์๋ค.
Chapter 6. The Java Virtual Machine Instruction Set
The wide instruction modifies the behavior of another instruction. It takes one of two formats, depending on the instruction being modified. The first form of the wide instruction modifies one of the instructions iload, fload, aload, lload, dload, istore,
docs.oracle.com
์ฐ๋ฆฌ๊ฐ ๋์ปดํ์ผํ ๊ฒฐ๊ณผ์์ ์ฐพ์๋ณผ ์ ์๋ค.
Code:
stack=4, locals=4, args_size=1
0: ldc #7 // String ์๋
2: astore_1
3: bipush 25
5: istore_2
6: new #9 // class Person
9: dup
10: aload_1
11: iload_2
12: invokespecial #11 // Method Person."<init>":(Ljava/lang/String;I)V
15: astore_3
16: aload_3
17: invokevirtual #14 // Method Person.print:()V
20: return
์ฐ๋ฆฌ๊ฐ ์ง ์์ค์ฝ๋์ ์๋ฐ ๋ฐ์ดํธ์ฝ๋๋ฅผ ๋ถ์ํ๊ธฐ ์ํด์ ์์์ผํ ๋ช๊ฐ์ง ๋ช ๋ น์ด๋ฅผ ์์๋ณด์
aload
: local variable ์ stack ์ push ํ๋คldc
: constant pool ์์๋ถํฐ #index ์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋คastore
: local variable ์ ๊ฐ์ ์ ์ฅํ๋ค.invokespecial
: instance Method ๋ฅผ ํธ์ถํ๊ณ ๊ฒฐ๊ณผ๋ฅผ stack ์ pushํ๋ค.new
: ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.invokevirtual
: ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.dup
: stack ์ ์๋ top ์ ๋ณต์ฌํ๋ค.
์ด์ธ์๋ ์ ๋ง ๋ง์ ๋ช ๋ น์ด๊ฐ ์กด์ฌํ๊ณ ์๋ฏธ๊ฐ ์กด์ฌํ๋๋ฐ, ํ๊ธ๋ก๋ ์ค๋ช ์ aroundck ๋์ ๋ธ๋ก๊ทธ ์์ ํ์ธํ ์ ์๋ค.
๋๊ธ