Java方法中本地变量的最大数量

6
我理解单一职责原则的重要性,但从技术角度来看,我们在每个Java方法中存储在堆栈帧中的局部变量数量是否有上限?并且这个上限是否等于最大堆栈大小?也就是说,我可以拥有一个大小等于最大堆栈大小配置的堆栈帧吗?

4
问题与单一职责原则有什么关联? - Ankur
1
好的。因此,关系在于一个方法中拥有太多的局部变量是不好的。在这种情况下,它可能会违反该原则。 - Bajji
你可以看一下这篇帖子:- https://dev59.com/CXA65IYBdhLWcg3wqQc8 - Rohit Jain
3个回答

5
我对这个明确的问题缺乏直接的答案感到惊讶,那么就来吧:JVM 的最大帧大小为 65535,本地变量的最大数量和最大堆栈大小也为 65535,其中 longdouble 每个占用两个条目。参考 JVM 规范 4.11. Java 虚拟机的限制:

  • 在调用方法(§2.6)时创建的帧的局部变量数组中的局部变量数目最多为 65535,由 Code 属性(§4.7.3)(给出该方法的代码)的 max_locals 项大小以及 Java 虚拟机指令集的 16 位局部变量索引限制。

    请注意,每个 long 和 double 类型的值都被认为是预留了两个局部变量,并且向 max_locals 值贡献了两个单位,因此使用这些类型的局部变量会进一步降低此限制。

  • 帧中操作数栈的大小(§2.6)受 Code 属性(§4.7.3)的 max_stack 字段限制,最多可以达到 65535。

    请注意,每个 long 和 double 类型的值都被认为向 max_stack 值贡献了两个单位,因此在操作数栈中使用这些类型的值会进一步降低此限制。

理论上来说,Java 语言可以通过将局部变量和堆栈卸载到堆中(因为堆可以更大)来解决 JVM 的限制问题,但在实践中它并没有真正做到-javac(至少截至 Java 15)会在您拥有 65535 个本地变量或堆栈深度为 65535 时报错。


应该是被接受的答案。 - Fizz

3

在定义本地变量数量时没有上限。如果您定义了太多无法放入堆栈帧中(或者)JVM无法为其大小分配堆栈帧,则会抛出StackOverflowError并退出。

有一位斯坦福教授的好讲座可能会对您有所帮助。


1
堆栈帧大小由您的方法定义决定。对于每个方法来说,它始终是相同的。 - Marko Topolnik
1
@Nambari,这对我来说不太对。大小已知,最大为65,536。 - Eugene
@Eugene:我也可能错了。如果您能提供官方参考资料支持您的评论,那么在更新答案之前,我很乐意使用您的评论。 - kosa
6
@Nambari 确认。 "i / aload" 接受一个字节参数作为输入,这个参数作为 LVA(局部变量数组)中的索引,可以有256个可能的值,因此最多可以有255个局部变量。除非使用 wide(http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings)在底部查看;然后它可以在 LVA 中使用16位索引,因此有65536个局部变量。 - Eugene
1
技术上讲,有65,535个本地变量而不是65,536个。 - ReubenBeeler
显示剩余3条评论

2
这将真正取决于您的运行时以及每个进程分配的堆栈空间量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接