【发布时间】:2023-03-18 22:24:03
【问题描述】:
那里有在堆栈上创建对象的 JVM 吗? 还是不通过引用计数器等与 Java 垃圾收集交互的 JVM?
假设我们在方法中创建了一个临时对象。 并且这个对象的引用永远不会在方法之外传递/存储/访问。 它只是在内部使用。
当遵循分配对象(在堆栈上,连同引用计数器)的经典方法时,必须注意以下步骤:
- 在堆中找到一个足以容纳对象的位置
- 分配空间
- 更新引用指针
- 使用垃圾回收注册对象
- [...对象被使用,最终被丢弃...]
- 识别垃圾收集
- 从堆中删除
- 从 GC 取消注册
因此,如果现在 VM 在堆栈上创建对象,则步骤 1、3、4、6、7、8 将不再需要,步骤 2 及其对应的 7 步将很容易进行堆栈管理。
那么是否有 JVM 对此进行了优化?
或者任何混合系统,比如在堆中分配对象,但不涉及正常的 GC,而是直接删除其范围末尾的对象?
是否有多个堆的实现(一个 GC 监督,另一个堆栈监督)?
【问题讨论】:
-
“或者 JVM 不通过引用计数器等与 Java 垃圾收集交互?” - java GC 不是引用计数
-
如果你有一个永远不会转义方法的对象,那么java可能会消除分配,它根本不会分配对象。因为 JIT 可以对热门方法进行这样的优化。
-
第 4、7 和 8 点在任何现实生活中的 JVM 中都不存在。没有注册表(除了具有非平凡终结器的对象)并且对象不会被“删除”。删除应该是什么?内存还在。在任何复杂的 JVM 中,第 1 点也不存在,请阅读有关 TLAB 的信息。他们也使第 2 点变得微不足道。唯一实际的问题是第 6 点。但是垃圾收集器不会针对单个对象运行。当内存已满或超过阈值时,它将针对 所有 个对象运行。
-
“引用计数”并不像你想象的那么轻量级,就像对象相互引用存在相当大的问题,然后你需要执行一些更高级的分析来找到它们,即使它们不是使用时间更长。 + 只是引用计数最终会产生碎片堆,这会减慢应用程序甚至浪费这么多内存应用程序将无法工作更长的时间。而且这种现代 GC 中只有很小一部分是 stop-the-world,大部分工作都是并行完成的,不会停止一切。
-
@JayC667 引用计数远非“简单和轻量级”。它要求对引用变量的所有更改都以线程安全的方式执行,并增加了原子计数器更新。然后,当计数器达到零时释放对象并不是免费的。它需要维护一个数据结构来保存所有这些微小的空闲内存碎片。复制或压缩垃圾收集器从不维护这样的数据结构。它仅在大块中运行。将开销分解为单个对象的一部分将产生比引用计数更少的开销。
标签: java memory-management jvm heap-memory