在看下面之前,可以自己尝试一下是否能将main方法字节码看懂public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V //方法描述,入参是String,返回是void flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=2, args_size=1 //栈深最大3,局部变量2,args_size入参是1(如果是实体方法会把this也算入参) 0: new #3 // class java8/ByteCodeDemo new指令创建对象,这里引用了常量池的class 所以这里一共占了三行 2个字节是class //一个字节是new,所以下个行号是 0+3 = 3 并把当前申请的空间地址放到栈顶 3: dup //将栈顶cpoy一份再次放入栈顶,也就是我们上面的空间地址 4: bipush 12 //取常量12放入栈空间 6: invokespecial #4 // Method "<init>":(I)V //执行初始化方法这个时候会用到4的栈顶,和3的栈顶,弹出 9: astore_1 //将栈顶放入局部变量,也就是0的空间地址,这个时候栈是空的 10: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; //获取这个方法地址到栈顶 13: new #6 // class java/lang/StringBuilder 把新开辟的空间地址放到栈顶 16: dup //复制一份 17: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V //弹出栈顶 20: ldc #8 // String name:xiaomingage://取常量到栈顶 22: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;//弹出栈顶两个元素,压入StringBuilder的引用 25: aload_1 // 把局部变量,也就是我们刚才的空间地址压入 26: invokevirtual #10 // Method getAge:()I //弹出栈顶,获取年龄,把年龄压入栈顶 29: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;//弹出栈顶两个元素,压入StringBuilder 32: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;//弹出栈顶两个元素,压入toString 35: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V//弹出栈顶两个元素,此时栈空 38: return //返回 LineNumberTable: //字节码偏移量到源代码行号之间的联系 line 29: 0 line 30: 10 line 31: 38}复制代码
思考:这里看懂了之后,大家可以自己尝试下自己写个稍微复杂的字节码,然后进行理解,加深一下印象。



| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |