thật ra bài này phải nói về cấu trúc của
file class thì đúng hơn, nhưng cũng chẳng có gì khác nhau hết, vốn dĩ chúng nó
là những thứ thuộc về nhau.
* Cấu trúc của một class file:
Mỗi định dạng có một cấu trúc riêng biệt và
nhất định, theo thời gian chúng thay đổi thì trình truy xuất dữ liệu từ chúng
cũng nâng cấp những phiên bản mới hơn. Điều này cũng giống như bản chất của một
con người, dù có thể thay đổi hình dạng đên đâu thì cũng không thể nào thay đổi
được chính con người mình, bạn có thể đổi tên từ a.class sang a.txt thì sao, nó
vẫn là một file class, chỉ có cái là người ta không nhận bản chất nó khi chỉ
nhìn từ cái tên.
[class]
-4b [magic header] mặc định khi chuyển qua
hex là CA FE BA BE
-2b [minor version] số nguyên của version x.
-2b [major version] phần thập phân của
version .x
-2b [số constant pool] các hằng sẵn có để sử
dụng trong class
- [mảng constant pool] bắt đầu 1b chỉ loại,
và tùy loại thì:
.1:chuỗi,
2b độ dài chuỗi a, ab dữ liệu chuỗi
.3:
số nguyên int: 4b giá trị số nguyên
.4:
số thập phân float: 4b giá trị số
.5:
số nguyên long: 8b giá trị số
.6:
số thập phân double: 8b giá trị số
.7:
kiểu class: 2b chỉ đến index của một constant chuỗi tên class trong mảng
.8:
chuỗi sử dụng trong method: 2b chỉ đến index của một consant chuỗi trong mảng
.9:
gọi biến dùng trong method, 2b chỉ đến index kiểu class, 2b chỉ đến kiểu bổ
nghĩa
.10.
gọi method dùng trong method, 2b chỉ đến index kiểu class, 2b chỉ đến kiểu bổ
nghĩa
.11:
gọi interface method dùng trong method, tương tự kiểu 10
.12:
bổ nghĩa, gồm tên và kiểu, 2b tên chỉ đến kiểu chuỗi (1), 2b kiểu chỉ đến kiểu
chuỗi (1).
-2b [access flag] truy xuất của class này.
-2b [this class] tên class, chỉ đến index của
một kiểu class (7).
-2b [super] tên class mà class này mở rộng
từ, chỉ đến index của kiểu class (7).
-2b [số interface] số implement(thực thi từ)
trong class .
- [mảng interface] chứa các tên class thực
thi, chỉ đến index của kiểu class(7).
-2b [số field] số các biến trong class.
- [mảng field] chứa các field, mỗi field có
cấu trúc:
.2b:
access flag
.2b:
tên biến, index đến kiểu chuỗi(1)
.2b:
kiểu biến, index đến kiểu chuỗi(1)
.2b:
số thuộc tính
.[bảng
thuộc tính]
-2b [số method] số method trong class
- [mảng method] chứa các method, mỗi method
có cấu trúc:
.2b:
access flag
.2b:
tên method, index đến kiểu chuỗi(1)
.2b:
định nghĩa method, index đến kiểu chuỗi(1)
.2b:
số thuộc tính
.[bảng
thuộc tính]
-2b [số attribute] số thuộc tính trong
class
- [mảng attribute] chứa các attribute
.2b:
tên thuộc tính, index đến kiểu chuỗi(1)
.4b:
độ dài thuộc tính a
.ab
[dữ liệu thuộc tính]
Class file thì chỉ có như vậy thôi, tất cả
đều được tạo nên từ constant pool và các opcode, phần opcode sẽ nói trong
bytecode. Nhất là opcode chỉ sử dụng trong method, cùng với đó là các constant
pool kiểu 3, 4, 5, 6, 8, 9, 10, 11. Các giá
trị thì lấy từ kiểu 3, 4, 5, 6, 8 còn code thì sử dụng 9, 10 ,11 kết hợp với
opcode nữa.
Chú ý một chút:
- Vì constant pool ở index 0 không được sử dụng, do đó nó luôn là null
và cũng không cần phải liệt kê trong mảng constant pool, vì vậy số constant
pool được liệt kê trong mảng constant pool luôn ít hơn số constant pool là 1.
- Đối với constant kiểu long (5) và double (6), thì cứ mỗi khi có một
constant kiểu như vậy, constant pool tiếp theo sẽ mang giá trị giống vậy, tức
là nó chiếm tới 2 constant pool.
- Thuộc tính của method có nhiều nhưng trong đó quan trọng nhất là
Code và StackMap. Khỏi phải nói thì cũng biết Code là để chứa code, còn
StackMap là để veritified class file.
[Code]
2b: tên (1)
4b: độ dài dữ liệu còn lại
2b: max stack
2b: max local
4b: độ dài code a
ab: dữ liệu code
2b: mảng exception {
.2b: start at
.2b: end at
.2b: handler
.2b: index đến một kiểu exception (1) }
2b: số thuộc tính phụ
[bảng thuộc tính phụ]
[StackMap]
2b: tên (1)
4b: độ dài dữ liệu còn lại
2b: số stack
[mảng stack] {
.2b: start at (offset frame)
.2b: số variable
.[mảng variable] { //bắt đầu 1b chỉ loại, tùy loại mà
0: 0b, 1: 0b, 2: 0b, 3: 0b, 4: 0b, 5: 0b, 6:
0b, 7: 2b, 8: 2b }
.2b: số stack
.[mảng stack] { //bắt đầu 1b chỉ loại, tùy loại mà
0: 0b, 1: 0b, 2: 0b, 3: 0b, 4: 0b, 5: 0b, 6:
0b, 7: 2b, 8: 2b }
OPCODE:
Cũng giống như khi bạn phân tích constant
pool vậy thôi, chỉ khác là constant chỉ có tới giá trị 12, ở đây ta có nhiều
giá trị hơn cho opcode. Mỗi giá trị ứng với một code và có số byte theo sau
khác nhau, theo sau đó có thể là một giá trị lấy trực tiếp hoặc là lấy từ
constant pool qua kiểu 3, 4, 5, 6, 8 hoặc là các kiểu code 9, 10, 11. Chỉ cần đọc là bạn sẽ hiểu. các giá trị được chuyển
qua hex cho đồng nhất
32: aaload
|
53: aastore
|
01:
aconst_null
|
19: aload ->1b: vị trí load
|
2a: aload_0
|
2b: aload_1
|
2c: aload_2
|
2d: aload_3
|
bd: anewarray ->2b: chỉ đến
kiểu class
|
b0: areturn
|
be: arraylength
|
3a: astore ->1b:vị trí lưu
|
4b: astore_0
|
4c: astore_1
|
4d: astore_2
|
4e: astore_3
|
bf: athrow
|
33: baload
|
54: bastore
|
10: bipush ->1b: giá trị
|
ca: breakpoint
|
34: caload
|
55: castore
|
c0: checkcast ->2b: chỉ đến
kiểu class
|
90: d2f
|
8e: d2i
|
8f: d2l
|
63: dadd
|
31: daload
|
52: dastore
|
98: dcmpg
|
97: dcmpl
|
0e: dconst_0
|
0f: dconst_1
|
6f: ddiv
|
18: dload ->1b: vị trí load
|
26: dload_0
|
27: dload_1
|
28: dload_2
|
29: dload_3
|
6b: dmul
|
77: dneg
|
73: drem
|
af: dreturn
|
39: dstore ->1b: vị trí lưu
|
47: dstore_0
|
48: dstore_1
|
49: dstore_2
|
4a: dstore_3
|
67: dsub
|
59: dup
|
5a: dup_x1
|
5b: dup_x2
|
5c: dup2
|
5d: dup2_x1
|
5e: dup2_x2
|
8d: f2d
|
8b: f2i
|
8c: f2l
|
62: fadd
|
30: faload
|
51: fastore
|
96: fcmpg
|
95: fcmpl
|
0b: fconst_0
|
0c: fconst_1
|
0d: fconst_2
|
6e: fdiv
|
17: fload ->1b: vị trí load
|
22: fload_0
|
23: fload_1
|
24: fload_2
|
25: fload_3
|
6a: fmul
|
76: fneg
|
72: frem
|
ae: freturn
|
38: fstore ->1b: vị trí lưu
|
43: fstore_0
|
44: fstore_1
|
45: fstore_2
|
46: fstore_3
|
66: fsub
|
b4: getfield ->2b: chỉ đến
kiểu 9
|
b2: getstatic ->2b: chỉ đến
kiểu 9
|
a7: goto ->2b: vị trí đi đến
|
c8: goto_w ->4b: vị trí đi
đến
|
91: i2b
|
92: i2c
|
87: i2d
|
86: i2f
|
85: i2l
|
93: i2s
|
60: iadd
|
2e: iaload
|
7e: iand
|
4f: iastore
|
03:
iconst_0
|
04:
iconst_1
|
05:
iconst_2
|
06:
iconst_3
|
07:
iconst_4
|
08:
iconst_5
|
02:
iconst_m1
|
6c: idiv
|
a5: if_acmpeq ->2b: vị trí
đi đến
|
a6: if_acmpne ->2b: vị trí
đi đến
|
9f: if_icmpeq ->2b: vị trí
đi đến
|
a2: if_icmpge ->2b: vị trí
đi đến
|
a3: if_icmpgt ->2b: vị trí
đi đến
|
a4: if_icmple ->2b: vị trí
đi đến
|
a1: if_icmplt ->2b: vị trí
đi đến
|
a0: if_icmpne ->2b: vị trí
đi đến
|
99: ifeq ->2b: vị trí đi đến
|
9c: ifge ->2b: vị trí đi đến
|
9d: ifgt ->2b: vị trí đi đến
|
9e: ifle ->2b: vị trí đi đến
|
9b: iflt ->2b: vị trí đi đến
|
9a: ifne ->2b: vị trí đi đến
|
c7: ifnonnull ->2b: vị trí
đi đến
|
c6: ifnull ->2b: vị trí đi
đến
|
84: iinc ->1b: vị trí load,
1b: chỉ số tăng
|
15: iload ->1b: vị trí load
|
1a: iload_0
|
1b: iload_1
|
1c: iload_2
|
1d: iload_3
|
fe: impdep1
|
ff: impdep2
|
68: imul
|
74: ineg
|
c1: instanceof ->2b: kiêu
class
|
ba: invokedynamic ->2b:
kiêểu 10, 1b: 0, 1b: 0
|
b9: invokeinterface ->2b:
kiêểu 11, 1b: số tham số method+1, 1b: 0
|
b7: invokespecial ->2b:
kiêều 10
|
b8: invokestatic ->2b: kiêều
11
|
b6: invokevirtual ->2b:
kiêều 12
|
80: ior
|
70: irem
|
ac: ireturn
|
78: ishl
|
7a: ishr
|
36: istore ->1b: vĩ trí lưu
|
3b: istore_0
|
3c: istore_1
|
3d: istore_2
|
3e: istore_3
|
64: isub
|
7c: iushr
|
82: ixor
|
a8: jsr ->2b: nhảy qua bao
nhieu byte
|
c9: jsr_w ->4b: nhảy qua bao
nhiêu byte
|
8a: l2d
|
89: l2f
|
88: l2i
|
61: ladd
|
2f: laload
|
7f: land
|
50: lastore
|
94: lcmp
|
9: lconst_0
|
0a: lconst_1
|
12: ldc ->1b: giá trị
constant pool
|
13: ldc_w ->2b: giá trị
constant pool
|
14: ldc2_w ->2b: giá trị
constant pool
|
6d: ldiv
|
16: lload ->1b: vị trí load
|
1e: lload_0
|
1f: lload_1
|
20: lload_2
|
21: lload_3
|
69: lmul
|
75: lneg
|
ab: lookupswitch ->0-3b: đệm
chia hết cho 4, 4b: default đi đến, 4b: số trường hợp,[trường hợp]{ 4b: giá
trị, 4b: vị trí đi]}
|
81: lor
|
71: lrem
|
ad: lreturn
|
79: lshl
|
7b: lshr
|
37: lstore ->1b: vị trí lưu
|
3f: lstore_0
|
40: lstore_1
|
41: lstore_2
|
42: lstore_3
|
65: lsub
|
7d: lushr
|
83: lxor
|
c2: monitorenter
|
c3: monitorexit
|
c5: multianewarray ->2b:
index class, 1b: số mảng con
|
bb: new ->2b: index class
|
bc: newarray ->1b: value
|
00:
nop
|
57: pop
|
58: pop2
|
b5: putfield ->2b: kiêều (9)
|
b3: putstatic ->2b: kiêểu
(9)
|
a9: ret
|
b1: return
|
35: saload
|
56: sastore
|
11: sipush ->2b: giá trị
|
5f: swap
|
aa: tableswitch ->0-3b: đệm
chia hết cho 4, 4b: default, mảng so sánh { 4b: giá trị so sánh, 4: nhảy đến}
|
c4: wide ->1b: opcode, nếu
opcode == iinc thì 4b ngược lại 2b
=================
|
Ngoài ra còn có:
B kiểu byte
C kiểu
char
D kiểu
double
F kiểu
Float
I kiểu
int
J kiểu
long
S kiểu short
Z kiểu
đúng sai (boolean)
L những kiểu khác thì thêm L này vào, kết
thúc là dấu “;” ví dụ La; là load a.class
V đây chính là void trong method đó
[ xác định là một array ví dụ [[I là
int[][]
Một số ví dụ:
a([[Iljava/lang/String;D)B là byte[]
a(int[][] i1,String i2, double i3)
.
2 nhận xét:
Hay lắm. Tks 4 share
đã update, chỉnh lại phần attribute, thuộc tính phụ chỉ tồn tại khi phân tích cụ thể từng loại thuộc tính
Đăng nhận xét