【JAVA】java字节码导读

深入学习java的话,一定会接触到class文件,也就会接触字节码,当你用记事本打开class文件,一堆看起来是乱码的东西,如果换另一种格式比如notepad++中安装HEX-Editor查看,便会是别有洞天。本文将从以下几个方面带你一起观看java中的惊天密码。

Eclipse中查看class文件

或许你知道eclipse中可以安装反编译插件去查看class文件,然而,我并不是这样去查看的,jdk安装的bin目录下一大堆好玩的有用的命令工具,为何还要用别的插件呢?我用到的就是javap命令,现在来配置eclipse。

  • elcipse中点击菜单栏中的Run>External Tools>External Tools Configurations出现的界面如下配置:
    这里写图片描述
    Name:随便命名(我的为javap-c)
    location:写入jdk安装目录下的bin目录下的javap.exe全路径
    Working Directory:填入 workspaceloc/ {project_name}
    Argumens:填入-c -classpath workspaceloc/ {project_name}/bin ${java_type_name}
    其实看配置也知道,是配置运行javap -c这个命令,这就是一个反编译命令。
  • 点击Apply完成

  • 新建一个类EqualsOrNot.java,我的代码如下:

package shamrock.javatezhongbing;

public class EqualsOrNot {
    public static void main(String[] args) {
          Object a="a"+"b";
          Object b= new String("ab");

          System.out.println(a==b);
          System.out.println(a.equals(b));
    } 
}
  • 点击Run>External Tools>javap-c(上面配置的Name),则控制台出现如下代码:
Compiled from "EqualsOrNot.java"
public class shamrock.javatezhongbing.EqualsOrNot {
  public shamrock.javatezhongbing.EqualsOrNot();
    Code:
       0: aload_0       
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16                 // String ab
       2: astore_1      
       3: new           #18                 // class java/lang/String
       6: dup           
       7: ldc           #16                 // String ab
       9: invokespecial #20                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
      12: astore_2      
      13: getstatic     #23                 // Field java/lang/System.out:Ljava/io/PrintStream;
      16: aload_1       
      17: aload_2       
      18: if_acmpne     25
      21: iconst_1      
      22: goto          26
      25: iconst_0      
      26: invokevirtual #29                 // Method java/io/PrintStream.println:(Z)V
      29: getstatic     #23                 // Field java/lang/System.out:Ljava/io/PrintStream;
      32: aload_1       
      33: aload_2       
      34: invokevirtual #35                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
      37: invokevirtual #29                 // Method java/io/PrintStream.println:(Z)V
      40: return        
}

这就是class文件反编译出来的字节码指令集,现在开始进行解读。

解析上面反编译出来的字节码指令集

 public shamrock.javatezhongbing.EqualsOrNot();
    Code:
       0: aload_0       
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return  

这部分是类默认会有一个不带参数的构造函数的字节码,重点讲main函数内的东西。
0: ldc #16 // String ab
表示将常量池中第#16存放的常量压入栈中,也就是将字符串”ab”压入栈顶中;
看程序源代码,你会发现, Object a=”a”+”b”;竟然在编译时就当成”ab”放入常量池了。
2: astore_1
表示将栈顶引用值弹出存入局部变量1中
3: new #18 // class java/lang/String
表示创建一个对象,并将引用值指向常量池的#18;
也就是说#18存放的是一个String类的引用值
6: dup
表示复制上面的引用值并压入栈顶
7: ldc #16 // String ab
表示将常量池中第#16存放的常量压入栈中,也就是将字符串”ab”压入栈顶中;
9: invokespecial #20 // Method java/lang/String.””:(Ljava/lang/String;)V
表示调用常量池#20作为入口的方法,该处是调用String的构造方法
12: astore_2
表示将栈顶引用值弹出存入局部变量2中
13:getstatic #23 // Field java/lang/System.out:Ljava/io/PrintStream;
表示调用静态方法,调用常量池#23为入口地址的静态方法
16:aload_1
表示局部变量1的值压入栈顶中
17: aload_2
表示局部变量2的值压入栈顶中
18: if_acmpne 25
表示判断弹出的栈顶两值的是否相等,不相等则跳转到25
21: iconst_1
表示将1压入栈顶
22: goto 26
表示跳转到26
25: iconst_0
表示将0压入栈顶
26: invokevirtual #29
表示调用常量池#29作为入口的实例方法

java字节码指令集汇总

MnemonicOpcodeOther bytesStack[before]→[after]Description
aaload32arrayref, index → valueload onto the stack a reference from an array
aastore53arrayref, index, value →store into a reference in an array
aconst_null01→ nullpush a null reference onto the stack
aload191: index→ objectrefload a reference onto the stack from a local variable #index
aload_02a→ objectrefload a reference onto the stack from local variable 0
aload_12b→ objectrefload a reference onto the stack from local variable 1
aload_22c→ objectrefload a reference onto the stack from local variable 2
aload_32d→ objectrefload a reference onto the stack from local variable 3
anewarraybd2: indexbyte1, indexbyte2count → arrayrefcreate a new array of references of length count and component type identified by the class referenceindex (indexbyte1 << 8 + indexbyte2) in the constant pool
areturnb0objectref → [empty]return a reference from a method
arraylengthbearrayref → lengthget the length of an array
astore3a1: indexobjectref →store a reference into a local variable #index
astore_04bobjectref →store a reference into local variable 0
astore_14cobjectref →store a reference into local variable 1
astore_24dobjectref →store a reference into local variable 2
astore_34eobjectref →store a reference into local variable 3
athrowbfobjectref → [empty], objectrefthrows an error or exception (notice that the rest of the stack is cleared, leaving only a reference to the Throwable)
baload33arrayref, index → valueload a byte or Boolean value from an array
bastore54arrayref, index, value →store a byte or Boolean value into an array
bipush101: byte→ valuepush a byte onto the stack as an integer value
breakpointcareserved for breakpoints in Java debuggers; should not appear in any class file
caload34arrayref, index → valueload a char from an array
castore55arrayref, index, value →store a char into an array
checkcastc02: indexbyte1, indexbyte2objectref → objectrefchecks whether an objectref is of a certain type, the class reference of which is in the constant pool at index (indexbyte1 << 8 + indexbyte2)
d2f90value → resultconvert a double to a float
d2i8evalue → resultconvert a double to an int
d2l8fvalue → resultconvert a double to a long
dadd63value1, value2 → resultadd two doubles
daload31arrayref, index → valueload a double from an array
dastore52arrayref, index, value →store a double into an array
dcmpg98value1, value2 → resultcompare two doubles
dcmpl97value1, value2 → resultcompare two doubles
dconst_00e→ 0.0push the constant 0.0 onto the stack
dconst_10f→ 1.0push the constant 1.0 onto the stack
ddiv6fvalue1, value2 → resultdivide two doubles
dload181: index→ valueload a double value from a local variable #index
dload_026→ valueload a double from local variable 0
dload_127→ valueload a double from local variable 1
dload_228→ valueload a double from local variable 2
dload_329→ valueload a double from local variable 3
dmul6bvalue1, value2 → resultmultiply two doubles
dneg77value → resultnegate a double
drem73value1, value2 → resultget the remainder from a division between two doubles
dreturnafvalue → [empty]return a double from a method
dstore391: indexvalue →store a double value into a local variable #index
dstore_047value →store a double into local variable 0
dstore_148value →store a double into local variable 1
dstore_249value →store a double into local variable 2
dstore_34avalue →store a double into local variable 3
dsub67value1, value2 → resultsubtract a double from another
dup59value → value, valueduplicate the value on top of the stack
dup_x15avalue2, value1 → value1, value2, value1insert a copy of the top value into the stack two values from the top. value1 and value2 must not be of the type double or long.
dup_x25bvalue3, value2, value1 → value1, value3, value2, value1insert a copy of the top value into the stack two (if value2 is double or long it takes up the entry of value3, too) or three values (if value2 is neither double nor long) from the top
dup25c{value2, value1} → {value2, value1}, {value2, value1}duplicate top two stack words (two values, if value1 is not double nor long; a single value, if value1 is double or long)
dup2_x15dvalue3, {value2, value1} → {value2, value1}, value3, {value2, value1}duplicate two words and insert beneath third word (see explanation above)
dup2_x25e{value4, value3}, {value2, value1} → {value2, value1}, {value4, value3}, {value2, value1}duplicate two words and insert beneath fourth word
f2d8dvalue → resultconvert a float to a double
f2i8bvalue → resultconvert a float to an int
f2l8cvalue → resultconvert a float to a long
fadd62value1, value2 → resultadd two floats
faload30arrayref, index → valueload a float from an array
fastore51arrayref, index, value →store a float in an array
fcmpg96value1, value2 → resultcompare two floats
fcmpl95value1, value2 → resultcompare two floats
fconst_00b→ 0.0fpush 0.0f on the stack
fconst_10c→ 1.0fpush 1.0f on the stack
fconst_20d→ 2.0fpush 2.0f on the stack
fdiv6evalue1, value2 → resultdivide two floats
fload171: index→ valueload a float value from a local variable #index
fload_022→ valueload a float value from local variable 0
fload_123→ valueload a float value from local variable 1
fload_224→ valueload a float value from local variable 2
fload_325→ valueload a float value from local variable 3
fmul6avalue1, value2 → resultmultiply two floats
fneg76value → resultnegate a float
frem72value1, value2 → resultget the remainder from a division between two floats
freturnaevalue → [empty]return a float
fstore381: indexvalue →store a float value into a local variable #index
fstore_043value →store a float value into local variable 0
fstore_144value →store a float value into local variable 1
fstore_245value →store a float value into local variable 2
fstore_346value →store a float value into local variable 3
fsub66value1, value2 → resultsubtract two floats
getfieldb42: index1, index2objectref → valueget a field value of an object objectref, where the field is identified by field reference in the constant pool index (index1 << 8 + index2)
getstaticb22: index1, index2→ valueget a static field value of a class, where the field is identified by field reference in the constant pool index (index1 << 8 + index2)
gotoa72: branchbyte1, branchbyte2[no change]goes to another instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
goto_wc84: branchbyte1, branchbyte2, branchbyte3, branchbyte4[no change]goes to another instruction at branchoffset (signed int constructed from unsigned bytes branchbyte1 << 24 + branchbyte2 << 16 + branchbyte3 << 8 + branchbyte4)
i2b91value → resultconvert an int into a byte
i2c92value → resultconvert an int into a character
i2d87value → resultconvert an int into a double
i2f86value → resultconvert an int into a float
i2l85value → resultconvert an int into a long
i2s93value → resultconvert an int into a short
iadd60value1, value2 → resultadd two ints
iaload2earrayref, index → valueload an int from an array
iand7evalue1, value2 → resultperform a bitwise and on two integers
iastore4farrayref, index, value →store an int into an array
iconst_m102→ -1load the int value -1 onto the stack
iconst_003→ 0load the int value 0 onto the stack
iconst_104→ 1load the int value 1 onto the stack
iconst_205→ 2load the int value 2 onto the stack
iconst_306→ 3load the int value 3 onto the stack
iconst_407→ 4load the int value 4 onto the stack
iconst_508→ 5load the int value 5 onto the stack
idiv6cvalue1, value2 → resultdivide two integers
if_acmpeqa52: branchbyte1, branchbyte2value1, value2 →if references are equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_acmpnea62: branchbyte1, branchbyte2value1, value2 →if references are not equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_icmpeq9f2: branchbyte1, branchbyte2value1, value2 →if ints are equal, branch to instruction at branchoffset (signed short constructed from unsigned bytesbranchbyte1 << 8 + branchbyte2)
if_icmpgea22: branchbyte1, branchbyte2value1, value2 →if value1 is greater than or equal to value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_icmpgta32: branchbyte1, branchbyte2value1, value2 →if value1 is greater than value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_icmplea42: branchbyte1, branchbyte2value1, value2 →if value1 is less than or equal to value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_icmplta12: branchbyte1, branchbyte2value1, value2 →if value1 is less than value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
if_icmpnea02: branchbyte1, branchbyte2value1, value2 →if ints are not equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
ifeq992: branchbyte1, branchbyte2value →if value is 0, branch to instruction at branchoffset (signed short constructed from unsigned bytesbranchbyte1 << 8 + branchbyte2)
ifge9c2: branchbyte1, branchbyte2value →if value is greater than or equal to 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
ifgt9d2: branchbyte1, branchbyte2value →if value is greater than 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
ifle9e2: branchbyte1, branchbyte2value →if value is less than or equal to 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
iflt9b2: branchbyte1, branchbyte2value →if value is less than 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
ifne9a2: branchbyte1, branchbyte2value →if value is not 0, branch to instruction at branchoffset (signed short constructed from unsigned bytesbranchbyte1 << 8 + branchbyte2)
ifnonnullc72: branchbyte1, branchbyte2value →if value is not null, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2)
ifnullc62: branchbyte1, branchbyte2value →if value is null, branch to instruction at branchoffset (signed short constructed from unsigned bytesbranchbyte1 << 8 + branchbyte2)
iinc842: index, const[No change]increment local variable #index by signed byte const
iload151: index→ valueload an int value from a local variable #index
iload_01a→ valueload an int value from local variable 0
iload_11b→ valueload an int value from local variable 1
iload_21c→ valueload an int value from local variable 2
iload_31d→ valueload an int value from local variable 3
impdep1fereserved for implementation-dependent operations within debuggers; should not appear in any class file
impdep2ffreserved for implementation-dependent operations within debuggers; should not appear in any class file
imul68value1, value2 → resultmultiply two integers
ineg74value → resultnegate int
instanceofc12: indexbyte1, indexbyte2objectref → resultdetermines if an object objectref is of a given type, identified by class reference index in constant pool (indexbyte1 << 8 + indexbyte2)
invokedynamicba4: indexbyte1, indexbyte2, 0, 0[arg1, [arg2 …]] →invokes a dynamic method identified by method reference index in constant pool (indexbyte1 << 8 + indexbyte2)
invokeinterfaceb94: indexbyte1, indexbyte2, count, 0objectref, [arg1, arg2, …] →invokes an interface method on object objectref, where the interface method is identified by method reference index in constant pool (indexbyte1 << 8 + indexbyte2)
invokespecialb72: indexbyte1, indexbyte2objectref, [arg1, arg2, …] →invoke instance method on object objectref, where the method is identified by method reference indexin constant pool (indexbyte1 << 8 + indexbyte2)
invokestaticb82: indexbyte1, indexbyte2[arg1, arg2, …] →invoke a static method, where the method is identified by method reference index in constant pool (indexbyte1 << 8 + indexbyte2)
invokevirtualb62: indexbyte1, indexbyte2objectref, [arg1, arg2, …] →invoke virtual method on object objectref, where the method is identified by method reference index in constant pool (indexbyte1 << 8 + indexbyte2)
ior80value1, value2 → resultbitwise int or
irem70value1, value2 → resultlogical int remainder
ireturnacvalue → [empty]return an integer from a method
ishl78value1, value2 → resultint shift left
ishr7avalue1, value2 → resultint arithmetic shift right
istore361: indexvalue →store int value into variable #index
istore_03bvalue →store int value into variable 0
istore_13cvalue →store int value into variable 1
istore_23dvalue →store int value into variable 2
istore_33evalue →store int value into variable 3
isub64value1, value2 → resultint subtract
iushr7cvalue1, value2 → resultint logical shift right
ixor82value1, value2 → resultint xor
jsra82: branchbyte1, branchbyte2→ addressjump to subroutine at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 + branchbyte2) and place the return address on the stack
jsr_wc94: branchbyte1, branchbyte2, branchbyte3, branchbyte4→ addressjump to subroutine at branchoffset (signed int constructed from unsigned bytes branchbyte1 << 24 + branchbyte2 << 16 + branchbyte3 << 8 + branchbyte4) and place the return address on the stack
l2d8avalue → resultconvert a long to a double
l2f89value → resultconvert a long to a float
l2i88value → resultconvert a long to a int
ladd61value1, value2 → resultadd two longs
laload2farrayref, index → valueload a long from an array
land7fvalue1, value2 → resultbitwise and of two longs
lastore50arrayref, index, value →store a long to an array
lcmp94value1, value2 → resultcompare two longs values
lconst_009→ 0Lpush the long 0 onto the stack
lconst_10a→ 1Lpush the long 1 onto the stack
ldc121: index→ valuepush a constant #index from a constant pool (String, int or float) onto the stack
ldc_w132: indexbyte1, indexbyte2→ valuepush a constant #index from a constant pool (String, int or float) onto the stack (wide index is constructed as indexbyte1 << 8 + indexbyte2)
ldc2_w142: indexbyte1, indexbyte2→ valuepush a constant #index from a constant pool (double or long) onto the stack (wide index is constructed as indexbyte1 << 8 + indexbyte2)
ldiv6dvalue1, value2 → resultdivide two longs
lload161: index→ valueload a long value from a local variable #index
lload_01e→ valueload a long value from a local variable 0
lload_11f→ valueload a long value from a local variable 1
lload_220→ valueload a long value from a local variable 2
lload_321→ valueload a long value from a local variable 3
lmul69value1, value2 → resultmultiply two longs
lneg75value → resultnegate a long
lookupswitchab4+: <0-3 bytes padding>, defaultbyte1, defaultbyte2, defaultbyte3, defaultbyte4, npairs1, npairs2, npairs3, npairs4, match-offset pairs…key →a target address is looked up from a table using a key and execution continues from the instruction at that address
lor81value1, value2 → resultbitwise or of two longs
lrem71value1, value2 → resultremainder of division of two longs
lreturnadvalue → [empty]return a long value
lshl79value1, value2 → resultbitwise shift left of a long value1 by value2 positions
lshr7bvalue1, value2 → resultbitwise shift right of a long value1 by value2 positions
lstore371: indexvalue →store a long value in a local variable #index
lstore_03fvalue →store a long value in a local variable 0
lstore_140value →store a long value in a local variable 1
lstore_241value →store a long value in a local variable 2
lstore_342value →store a long value in a local variable 3
lsub65value1, value2 → resultsubtract two longs
lushr7dvalue1, value2 → resultbitwise shift right of a long value1 by value2 positions, unsigned
lxor83value1, value2 → resultbitwise exclusive or of two longs
monitorenterc2objectref →enter monitor for object (“grab the lock” - start of synchronized() section)
monitorexitc3objectref →exit monitor for object (“release the lock” - end of synchronized() section)
multianewarrayc53: indexbyte1, indexbyte2, dimensionscount1, [count2,…] → arrayrefcreate a new array of dimensions dimensions with elements of type identified by class reference in constant pool index (indexbyte1 << 8 + indexbyte2); the sizes of each dimension is identified bycount1, [count2, etc.]
newbb2: indexbyte1, indexbyte2→ objectrefcreate new object of type identified by class reference in constant pool index (indexbyte1 << 8 + indexbyte2)
newarraybc1: atypecount → arrayrefcreate new array with count elements of primitive type identified by atype
nop00[No change]perform no operation
pop57value →discard the top value on the stack
pop258{value2, value1} →discard the top two values on the stack (or one value, if it is a double or long)
putfieldb52: indexbyte1, indexbyte2objectref, value →set field to value in an object objectref, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 + indexbyte2)
putstaticb32: indexbyte1, indexbyte2value →set static field to value in a class, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 + indexbyte2)
reta91: index[No change]continue execution from address taken from a local variable #index (the asymmetry with jsr is intentional)
returnb1→ [empty]return void from method
saload35arrayref, index → valueload short from array
sastore56arrayref, index, value →store short to array
sipush112: byte1, byte2→ valuepush a short onto the stack
swap5fvalue2, value1 → value1, value2swaps two top words on the stack (note that value1 and value2 must not be double or long)
tableswitchaa4+: [0-3 bytes padding], defaultbyte1, defaultbyte2, defaultbyte3, defaultbyte4, lowbyte1, lowbyte2, lowbyte3, lowbyte4, highbyte1, highbyte2, highbyte3, highbyte4, jump offsets…index →continue execution from an address in the table at offset index
widec43/5: opcode, indexbyte1, indexbyte2
or
iinc, indexbyte1, indexbyte2, countbyte1, countbyte2[same as for corresponding instructions]execute opcode, where opcode is either iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, or ret, but assume the index is 16 bit; or execute iinc, where the index is 16 bits and the constant to increment by is a signed 16 bit short
(no name)cb-fdthese values are currently unassigned for opcodes and are reserved for future use
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值