谈JVM,字节码

谈谈JVM,最近在研究破解jar,有这方面经验的麻烦指导一下思路..

参考

参考1
指令整理

常用指令

1
2
3

# 反编译查看`类文件`所有信息
javap -verbose [class]

局部变量类型

特殊字符表示 类型 描述
c char char类型
i int int类型
l long long类型
s short short类型
b byte byte类型
f float float类型
z boolean 布尔类型
a reference 引用

方法信息

1
2
3
4
5
L1
LOCALVARIABLE this LMain; L0 L1 0
LOCALVARIABLE a I L0 L1 1
MAXSTACK = 0
MAXLOCALS = 2

局部变量参数 LOCALVARIABLE
局部表大小 MAXLOCALS
操作数栈大小 MAXSTACK

指令

运算指令

算术指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶。

  • 加法指令:iadd,ladd,fadd,dadd
  • 减法指令:isub,lsub,fsub,dsub
  • 乘法指令:imul,lmul,fmul,dmul
  • 除法指令:idiv,ldiv,fdiv,ddiv
  • 求余指令:irem,lrem,frem,drem
  • 取反指令:ineg,leng,fneg,dneg
  • 位移指令:ishl,ishr,iushr,lshl,lshr,lushr
  • 按位或指令:ior,lor
  • 按位与指令:iand,land
  • 按位异或指令:ixor,lxor
  • 局部变量自增指令:iinc
  • 比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

加载和存储指令

用于局部变量表操作数栈之间来回传输

  • 将一个局部变量加载到操作数栈的指令包括:iload,iload_<n>,lload、lload_<n>、float、fload_<n>、dload、dload_<n>,aload、aload_<n>。
  • 将一个数值从操作数栈存储到局部变量标的指令:istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
  • 将常量加载到操作数栈的指令:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_<i>,lconst_<l>,fconst_<f>,dconst_<d>
  • 局部变量表的访问索引指令:wide
    一部分以尖括号结尾的指令代表了一组指令,如iload_<i>,代表了iload_0,iload_1等,这几组指令都是带有一个操作数的通用指令。

运算指令

对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈

  • 加法指令:iadd,ladd,fadd,dadd
  • 减法指令:isub,lsub,fsub,dsub
  • 乘法指令:imul,lmul,fmul,dmul
  • 除法指令:idiv,ldiv,fdiv,ddiv
  • 求余指令:irem,lrem,frem,drem
  • 取反指令:ineg,leng,fneg,dneg
  • 位移指令:ishl,ishr,iushr,lshl,lshr,lushr
  • 按位或指令:ior,lor
  • 按位与指令:iand,land
  • 按位异或指令:ixor,lxor
  • 局部变量自增指令:iinc
  • 比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

类型转换指令

将两种Java虚拟机数值类型相互转换

JVM支持宽化类型转换(小范围类型向大范围类型转换):

  • int类型到long,float,double类型
  • long类型到float,double类型
  • float到double类型

对象创建与操作

虽然类实例和数组都是对象,Java虚拟机对类实例和数组的创建与操作使用了不同的字节码指令。

  • 创建实例的指令:new
  • 创建数组的指令:newarray,anewarray,multianewarray
  • 访问字段指令:getfield,putfield,getstatic,putstatic
  • 把数组元素加载到操作数栈指令:baload,caload,saload,iaload,laload,faload,daload,aaload
  • 将操作数栈的数值存储到数组元素中执行:bastore,castore,castore,sastore,iastore,fastore,dastore,aastore
  • 取数组长度指令:arraylength
  • 检查实例类型指令:instanceof,checkcast

操作数栈管理指令

直接操作操作数栈的指令:pop,pop2,dup,dup2,dup_x1,dup2_x1,dup_x2,dup2_x2和swap

NOTE: 压入栈顶(DUP)/弹出栈顶(POP)

控制转移指令

  • 条件分支:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnotnull,if_cmpeq,if_icmpne,if_icmlt,if_icmpgt等
  • 复合条件分支:tableswitch,lookupswitch
  • 无条件分支:goto,goto_w,jsr,jsr_w,ret

方法调用和返回指令

  • invokevirtual指令:调用对象的实例方法,根据对象的实际类型进行分派(虚拟机分派)。
  • invokeinterface指令:调用接口方法,在运行时搜索一个实现这个接口方法的对象,找出合适的方法进行调用。
  • invokespecial:调用需要特殊处理的实例方法,包括实例初始化方法,私有方法和父类方法
  • invokestatic:调用类方法(static)
  • 方法返回指令是根据返回值的类型区分的,包括ireturn(返回值是boolean,byte,char,short和int),lreturn,freturn,drturn和areturn,另外一个return供void方法,实例初始化方法,类和接口的类初始化i方法使用。

同步

Eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// class version 52.0 (52)
// access flags 0x21
public class Main {

// compiled from: Main.java

// access flags 0x11
public final I simpleField = 100

// access flags 0x0
<init>()V
L0
LINENUMBER 12 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
L1
LINENUMBER 10 L1
ALOAD 0
BIPUSH 100
PUTFIELD Main.simpleField : I
L2
LINENUMBER 13 L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
BIPUSH 100
INVOKEVIRTUAL java/io/PrintStream.print (I)V
L3
LINENUMBER 14 L3
RETURN
L4
LOCALVARIABLE this LMain; L0 L4 0
MAXSTACK = 2
MAXLOCALS = 1

// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 16 L0
NEW Main
DUP
INVOKESPECIAL Main.<init> ()V
ASTORE 1
L1
LINENUMBER 17 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "-->"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 19 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE main LMain; L1 L3 1
MAXSTACK = 2
MAXLOCALS = 2

// access flags 0x21
public synchronized a(I)V throws java/lang/Exception
L0
LINENUMBER 23 L0
RETURN
L1
LOCALVARIABLE this LMain; L0 L1 0
LOCALVARIABLE a I L0 L1 1
MAXSTACK = 0
MAXLOCALS = 2
}
分享到