μ°λ¦¬λ λ§μ μκ° 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λ₯Ό μ°Έκ³ νλ©΄ λλ€.
Constant Pool
JVMμ Host OS μ λ©λͺ¨λ¦¬λ₯Ό μ΅λν ν¨μ¨μ μΌλ‘ μ΄μ©νλλ‘ μ€κ³κ° λμ΄μλ€.
μ΄λ₯Ό μν΄μ JVMμ Constant Pool μ΄λΌλ μ λ΅μ μ¬μ©νλλ°, JVMμ΄ λμ μΌλ‘ μ½λλ₯Ό μ€νμν¬ λ λͺ¨λ λ°μ΄ν°λ₯Ό μ¦μ μμ±νλ κ²μ΄ μλλΌ Constant Pool μ μ μ₯νκ³ Constant Pool μ μ‘΄μ¬νλ λ°μ΄ν°λ₯Ό μ°μ μ μΌλ‘ κ°μ Έμ λ©λͺ¨λ¦¬λ₯Ό λμ± ν¨μ¨μ μΌλ‘ μ¬μ©ν μ μκ² λλ κ²μ΄λ€.
#
ννμ ν΄μμ½λλ‘ μμνλ κ²μ΄ νΉμ§μ΄λ€.
μ΄ Constant Poolμ λν΄μλ ν΄λΉ λΈλ‘κ·Έμ μ‘°κΈ λ κΉμ Java - String Constant Pool μμ νμΈν μ μλ€.
Instruction Set
μλ° λ°μ΄νΈμ½λλ μ»΄νμΌλ κ²°κ³Όλ‘ μμ±λλ μ½λ μ΄λ―λ‘ μΌμ’ μ λͺ λ Ήμ΄ μ§ν©μ΄λΌκ³ ν μ μλ€.
μ΄λ₯Ό JVM Instruction Set μ΄λΌκ³ νλ€.
λͺ λ Ήμ΄λ λΉμ°νκ² OpCodeμ Operands λ‘ κ΅¬μ±λλλ° μλ° λ°μ΄νΈμ½λμμλ 1 Byteμ OpCodeμ 2 Byteμ Operands λ‘ κ΅¬μ±λλ€.
1 Byteμ OpCode μ΄λ―λ‘ μ¬μ©κ°λ₯ν μ΄ λͺ λ Ήμ΄μ μλ 256κ°κ° λκ³ μμΈν λͺ λ Ήμ΄μ μ μλ Oracle Java Bytecode Instruction Set Docs μμ νμΈν μ μλ€.
μ°λ¦¬κ° λμ»΄νμΌν κ²°κ³Όμμ μ°Ύμλ³Ό μ μλ€.
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 λμ λΈλ‘κ·Έ μμ νμΈν μ μλ€.
λκΈ