默认堆栈大小是多少,它可以增长吗,它如何与垃圾回收一起工作?

2022-08-31 11:44:52

我知道每个线程都有自己的.基元类型和引用保留在堆栈上,并且堆栈上不保留任何对象。stack

我的问题是:

  • 堆栈可以增长多少?(像参数一样 - 和 -XmsXmx)
  • 我们能限制它的增长吗?
  • 堆栈是否有默认的最小值和最大值?
  • 垃圾回收如何在堆栈上工作?

答案 1

堆栈可以增长多少?

可以使用名为 VM 的选项来调整最大堆栈大小。VM 选项通常使用 -X{option} 传递。因此,您可以使用 将最大堆栈大小设置为 1M。ssjava -Xss1M

每个线程至少有一个堆栈。一些Java虚拟机(JVM)将Java堆栈(Java方法调用)和本机堆栈(VM中的本机方法调用)放入一个堆栈中,并使用“托管到本机框架”(称为M2nFrame)执行堆栈展开。某些 JVM 分别保留两个堆栈。在大多数情况下,设置 Java 堆栈的大小。Xss

对于许多 JVM,它们在不同的平台上为堆栈大小设置了不同的默认值。


我们能限制这种增长吗?

发生方法调用时,将在该线程的堆栈上创建新的堆栈帧。堆栈将包含局部变量、参数、返回地址等。在Java中,您永远不能将对象放在堆栈上,只有对象引用可以存储在堆栈上。由于数组在Java中也是一个对象,因此数组也不存储在堆栈上。因此,如果通过将局部基元变量、参数分组到对象中来减少这些参数的数量,则可以减少堆栈上的空间。实际上,我们无法将对象显式放在Java堆栈上的事实会影响性能一段时间(缓存未命中)。


堆栈是否有一些默认的最小值或默认的最大值?

如前所述,不同的 VM 是不同的,并且可能会因版本而异。请参阅此处


垃圾回收如何在堆栈上工作?

Java中的垃圾回收是一个热门话题。垃圾回收旨在收集中无法访问的对象。因此,这需要一个“可访问”的定义。堆栈上的所有内容都构成 GC 中根集引用的一部分。从每个线程的每个堆栈中可访问的所有内容都应被视为实时。还有其他一些根集引用,如 Thread 对象和一些类对象。

这只是GC上堆栈的非常模糊的使用。目前,大多数JVM都在使用代际GC。本文简要介绍了 Java GC。最近,我读了一篇非常好的文章,谈论.NET平台上的GC。Oracle JVM上的GC非常相似,所以我认为这可能也会对你有所帮助。


答案 2

正如你所说,局部变量和引用存储在堆栈上。当方法返回时,堆栈指针只是被移回方法启动之前的位置,即所有本地数据都“从堆栈中删除”。因此,堆栈上不需要垃圾回收,这只发生在堆中。

要回答您的具体问题:

  • 请参阅此问题,了解如何增加堆栈大小。
  • 您可以通过以下方式限制堆栈增长:
    • 将对象中的许多局部变量分组:该对象将存储在堆中,并且只有引用存储在堆栈上
    • 限制嵌套函数调用的次数(通常不使用递归)
  • 对于 Windows,32 位的默认堆栈大小为 320k,64 位的默认堆栈大小为 1024k,请参阅此链接