μ°λ¦¬λ λ§μ μκ° 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 λμ λΈλ‘κ·Έ μμ νμΈν μ μλ€.
λκΈ