本文反汇编的版本是1.8
对主要几个变量初始化过程进行了解析
代码如下
public int testForException() {
int a = 'a';
char c1 = 'a';
int i1 = 1;
double d1 = 0.2;
long l1 = 100l;
EntityFF entityFF = new EntityFF();
entityFF.getName();
return 1;
}
反汇编如下
Code:
stack=2, locals=9, args_size=1
0: bipush 97
2: istore_1
3: bipush 97
5: istore_2
6: iconst_1
7: istore_3
8: ldc2_w #16 // double 0.2d
11: dstore 4
13: ldc2_w #18 // long 100l
16: lstore 6
18: new #20 // class com/smp/util/fordev/EntityFF
21: dup
22: invokespecial #22 // Method com/smp/util/fordev/EntityFF."<init>":()V
25: astore 8
27: aload 8
29: invokevirtual #23 // Method com/smp/util/fordev/EntityFF.getName:()Ljava/lang/String;
32: pop
33: iconst_1
34: ireturn
常量池如下
Constant pool:
#1 = Class #2 // com/smp/util/fordev/MainFunc
#2 = Utf8 com/smp/util/fordev/MainFunc
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Methodref #3.#9 // java/lang/Object."<init>":()V
#9 = NameAndType #5:#6 // "<init>":()V
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/smp/util/fordev/MainFunc;
#14 = Utf8 testForException
#15 = Utf8 ()I
#16 = Double 0.2d
#18 = Long 100l
#20 = Class #21 // com/smp/util/fordev/EntityFF
#21 = Utf8 com/smp/util/fordev/EntityFF
#22 = Methodref #20.#9 // com/smp/util/fordev/EntityFF."<init>":()V
#23 = Methodref #20.#24 // com/smp/util/fordev/EntityFF.getName:()Ljava/lang/String;
#24 = NameAndType #25:#26 // getName:()Ljava/lang/String;
#25 = Utf8 getName
#26 = Utf8 ()Ljava/lang/String;
#27 = Utf8 a
#28 = Utf8 I
#29 = Utf8 c1
#30 = Utf8 C
#31 = Utf8 i1
#32 = Utf8 d1
#33 = Utf8 D
#34 = Utf8 l1
#35 = Utf8 J
#36 = Utf8 entityFF
#37 = Utf8 Lcom/smp/util/fordev/EntityFF;
#38 = Utf8 SourceFile
#39 = Utf8 MainFunc.java
1、将'a'复制给int或者char都是当做int去处理的,这里用了bipush 如果数值是-1~5的话 用的是iload,这里可以看到int a = 'a' 和char a = 'a'是一样的字节码,所以二者不存在效率区别
2、变量初始化的过程一般是两步,第一步加载到操作数栈,第二部从操作数栈加载到变量里。
3、double和long使用的都是ldc2_w指令,long类型如果数值小的话是lconst
4、对象新建的过程有很多,这里只给了new的例子,首先new一个对象,new的操作数是指向常量池的#20,对应一个class,class包含一个操作数是类名,指向#21,new指令的操作是创建一个对象,将其引用进栈,dup是复制栈顶元素,将复制值入栈。
5、调用方法也是调用常量池,常量池中的参数引用通常也来源于常量池,通过对应名字都可以看出大概意思
6、其中方法的表示()V就表示没有参数,返回值为void的函数,如果是(I)I就是参数是int,返回值是int,如果参数是String之类的对象,这里用的就是全限定名