【问题标题】:Can a Java method have more than 255 local variables?Java 方法可以有超过 255 个局部变量吗?
【发布时间】:2012-12-24 22:10:36
【问题描述】:

iload Java 操作码用于将值从局部变量数组 (LVA) 压入操作数堆栈。

此操作码将单个字节作为参数 (en.wikipedia.org/wiki/Java_bytecode_instruction_listings),用作 LVA 的索引。

如果 LVA 的一个元素始终是对对象的引用(我想这不是静态方法的情况,但现在让我们忽略这些),并且如果恰好一个字节用作索引(256 可能values),那么一个方法怎么能访问超过 255 个不同的局部变量呢?

【问题讨论】:

  • 当你尝试时会发生什么?

标签: java jvm bytecode low-level opcode


【解决方案1】:

是的,Java 方法可以有超过 255 个局部变量。 wide 操作码指令可用于修改 iloadaload 指令以使用 16 位索引而不是 8 位索引,这意味着函数中最多可以有 65536 个不同的局部变量,只要wide 操作码最终被使用。

也就是说,请注意,Java 局部变量不一定与 JVM 局部变量一一对应。 Java 编译器可能会查看您的代码,注意到局部变量的空间可以在某些上下文中重用,然后将多个 Java 局部变量映射到相同的 JVM 局部变量。

希望这会有所帮助!

【讨论】:

  • 我认为 (OpenJDK) javac 不会那样做。我怀疑它也不使用wide。我没有在这台机器上安装 Java 来测试它(我也懒得看代码)。
  • @TomHawtin-tackline- 我不确定javac 的任何特定实现是否会这样做,但原则上可以这样做(因为 JVM 支持它)。如果您知道这方面的任何参考资料,我很乐意看到它们。
  • 似乎至少有一个编译器确实这样做了 - 请参阅另一个答案。
  • 单个函数内的 65536 个变量是无法达到的限制,因为函数的最大大小为 65535 字节。
【解决方案2】:

我通过编写一个包含 300 个本地变量的程序为您进行了尝试。这个sn-p:

System.out.println(a255);
System.out.println(a256);

编译成这样:

3575: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
3578: iload         255
3580: invokevirtual #53                 // Method java/io/PrintStream.println:(I)V
3583: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
3586: iload_w       #256                // Utf8 a196
3590: invokevirtual #53                 // Method java/io/PrintStream.println:(I)V

注意:用 Eclipse 和 javac 编译,结果完全相同。

【讨论】:

  • 我的意思是C4 15 01 00iload_w #256 是指令,而不是操作码。
  • 恐怕javap 不会那样做。如果你知道方法,我会做的。
  • 我认为您不想在十六进制编辑器中打开 class 文件?
  • 然后将所有字节转储给您?这对你有什么帮助?
  • 有这个重复序列:c4 15 01 00 b6 00 35 b2 00 10c4 15 01 01 b6 00 35 b2 00 10...第四个字节不断增加。
猜你喜欢
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 2015-03-08
相关资源
最近更新 更多