有关Java中'new'关键字的内存问题

8
如果运行以下代码会发生什么?
while (true) {
    String x = new String("ABC");
}

关于内存方面的问题?

String x 是在栈上还是堆上分配的?程序是否会因为内存溢出而崩溃,还是会被垃圾回收机制阻止?new 关键字是否总是在堆上创建对象?什么时候会在栈上创建对象?

谢谢!


1
你可能想看一下http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3。 - Chetter Hummin
嗨Rohan,请一个问题一个问题地问。 - MByD
这些是相关的问题,所以我将它们合并在一起,以便我(和其他人)可以对这个主题有一个广泛的了解! - Rohan Agarwal
我同意它们是相关的,但在我看来它们应该被分开,而且我认为每个问题在 Stack Overflow 上都已经被回答了至少 5 次。 - MByD
所有不可访问的对象都将被标记为可回收。 - Subhrajyoti Majumder
3个回答

7

字符串x是在堆栈上还是堆上分配的?

x不是一个 String。它是对 String 的引用。该引用是局部变量,因此放在堆栈上。而 String 是一个对象,所以放在堆上。

程序最终会因内存溢出而崩溃吗?

很可能不会。

还是垃圾回收程序会防止这种情况发生?

应该会。

new 关键字是否总是在堆上创建对象?

是的。

什么时候会在堆栈上创建一个对象?

从来没有...除非 JVM 认为它无法逃离当前作用域,因此决定这样做。


1
这不完全是我的专业领域,但这种情况不是对象无法逃离当前作用域,因此逃逸分析导致字符串在堆栈上分配的情况吗? - mikera
是的,程序不会崩溃,我一直运行这段代码片段很长时间了,程序仍在运行。好答案!(+1) - asifsid88
1
@mikera 当然,如果JVM进行逃逸分析的话。我在上一句话中已经这么说了。 - user207421

2
使用 new 命令会将对象放在堆上。任何线程都无法访问的对象可以被垃圾回收。程序是否会耗尽内存取决于程序使用数据的大小,以及您是否擅长“释放”不再需要的对象(请注意:内存泄漏是不好的)。
在您的示例中,垃圾回收器将会频繁运行,我认为这就是您想要演示的内容。
局部变量则存储在栈中。

-1

理论上,new 在堆上创建对象,而非对象(例如 intchar 等)则在栈上创建。唯一的例外是字符串,也会在栈上创建。实际上,许多现代 JVM 的 JIT 编译器会发现,在某些情况下,使用 new 创建的对象可以在栈上创建(例如,局部对象在当前函数之外没有被引用)。

垃圾回收器将为您处理释放内存的工作,这是它的目的,但如果您同时创建并保留太多对象的引用,就可能会耗尽内存(例如,尝试创建一个包含十亿个字符串的列表)。


栈中的字符串没有异常。 - user207421

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