热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java字节码中的堆栈=4.JavaCompiler如何计算4值?(堆栈的深度)

如何解决《Java字节码中的堆栈=4.JavaCompiler如何计算4值?(堆栈的深度)》经验,为你挑选了1个好方法。

Java代码:

public class SimpleRecursion {

    public int factorial(int n) {
        if (n == 0) {
            return 1;
        }
        return n*factorial(n - 1);
    }

}

为factorial方法提供以下字节码(我执行javap来生成它):

public int factorial(int); 
descriptor: (I)I 
flags: ACC_PUBLIC 
Code:   
  stack=4, locals=2, args_size=2
     0: iload_1
     1: ifne          6
     4: iconst_1
     5: ireturn
     6: iload_1
     7: aload_0
     8: iload_1
     9: iconst_1
    10: isub
    11: invokevirtual #2                  // Method factorial:(I)I
    14: imul
    15: ireturn   
  LineNumberTable:
    line 4: 0
    line 5: 4
    line 7: 6   
  StackMapTable: number_of_entries = 1
    frame_type = 6 /* same */

据我所知,在上面的第五行中,stack = 4意味着堆栈最多可以有4个对象.

但是编译器如何计算呢?



1> Holger..:

由于堆栈的初始状态以及每条指令对它的影响是众所周知的,因此您可以随时精确地预测哪些项目将位于操作数堆栈上:

[ ]            // initially empty
[ I ]          0: iload_1
[ ]            1: ifne          6
[ I ]          4: iconst_1
[ ]            5: ireturn
[ I ]          6: iload_1
[ I O ]        7: aload_0
[ I O I ]      8: iload_1
[ I O I I ]    9: iconst_1
[ I O I ]     10: isub
[ I I ]       11: invokevirtual #2   // Method factorial:(I)I
[ I ]         14: imul
[ ]           15: ireturn   

JVM的验证器将完全执行此操作,在每条指令之后预测堆栈的内容,以检查它是否适合作为后续指令的输入.但是,这有助于具有声明的最大大小,因此验证者不需要维护动态增长的数据结构或为理论上可能的64k堆栈条目预分配内存.使用声明的最大大小,它可以在遇到超过该指令的指令时停止,因此它永远不需要比声明更多的内存.

如您所见,声明的最大堆栈大小恰好iconst_1在索引9处的指令之后达到一次.

然而,这并不意味着编译器必须执行这样的指令分析.编译器具有从源代码派生的代码的更高级别模型,称为抽象语法树.

该结构将用于生成结果字节码,并且它还可以预测该级别上所需的堆栈大小.但编译器实际上是如何做到的,取决于实现.


推荐阅读
author-avatar
手机用户2502906263
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有