Java无限循环何时停止?

3

我了解到无限循环在某些语言中会在堆栈溢出或达到分配的最大内存时停止。而其他语言则根据程序类型和语言不同可能会一直循环下去。

我的问题是,Java的无限循环会停止吗?我很好奇因为Java有垃圾回收器,在内存泄漏时可以重用内存,以防止达到分配的最大内存和堆栈溢出。

此外,这种类型的无限循环会停止吗?

for( ; ; ){}

1
这个循环不会停止,因为它根本就不会开始。Java的优化编译器会发现该循环没有任何作用和副作用,并消除死代码。 - Andrew Bissell
当时间耗尽或进程被终止时,它们会停止 :) - David Sainty
1
@Andrew Bissell - 当我尝试这样做时,Eclipse和JRE都会给我一个关于循环后不可达代码的错误。如果循环后没有代码,它仍然会执行并且永远无法通过它。 - user439793
@AndrewBissell 如果你像这样声明一个变量 boolean run = true 并使用 while(run) { },它会通过,因为它可以被其他线程更改,但如果没有更改,你将得到一个无限循环。 - Diego C Nascimento
@paxdiablo 规范允许优化器假定循环最终会终止。否则将会惩罚大量代码。 - David Schwartz
显示剩余8条评论
3个回答

7
我的问题是,Java的无限循环会停止吗?
有些会停止,有些不会。这取决于循环的实现方式。
基本上,你在其他语言中认为会停止的情况,在Java中也可能会停止…这取决于你如何编写它们。
  • 通过无限递归实现的循环将导致堆栈溢出。在Java中比一些语言更容易“实现”。(没有尾调用优化。)
  • 如果循环重复分配对象并保持可访问性,则会发生堆溢出…以便GC无法回收它们。
(还有其他一些看似无限循环可以终止的方法。)
我只是好奇因为Java有垃圾回收器,当存在内存泄漏时,它会重新使用内存以防达到最大内存和堆栈溢出。
垃圾回收器回收不可访问的对象,但是可访问的对象(即将来可能被程序使用的对象)无法回收。
垃圾回收器不处理堆栈内存,因此与堆栈溢出故障无关。
此类无限循环会停止吗?
不会。
严格来说,任何循环都不是无限的,如果它因任何原因停止…这包括堆栈溢出或内存耗尽等原因。
但是,即使是无限循环也不是真正的无限。最终,用户将杀死循环程序,电源将关闭,硬件将被报废…或类似的事情。

3
我认为没有人把“无限循环”中的“无限”理解为数学上的无穷大。它更像是“一个没有有效限制继续执行的循环”。 - Ted Hopp
1
@TedHopp - 我相信有人会这么想。实际上,如果有人不觉得这一点有点令人困惑...起初我会感到惊讶。此外,“没有任何有效限制”实际上很难定义其含义。因此,在我看来,值得提及这些问题。 - Stephen C

3

无限循环不会停止,除非有其他原因导致整个程序崩溃 :-)

通常情况下,这是由于资源短缺引起的,比如在无限递归的情况下是堆栈空间不足,或者在循环中分配了一些内存(但未释放),导致内存耗尽。

垃圾回收只会丢弃垃圾。如果内存仍然可以被变量访问,则不被视为垃圾。

换句话说,如果你的无限循环每次都向链表末尾添加一个元素(并且你没有失去对头部的访问权限),那么所有这些节点都不会被垃圾回收,最终会导致内存耗尽。

你的那个特定的循环:

for (;;) {}

由于它未使用任何资源,因此循环实际上不会停止。当然,你可以终止该进程,或者你可能有一个单独的线程使用资源。这两种情况(以及其他事件)可能导致循环停止,但它们都在该循环的控制范围之外。


2

如果内存在循环中增长,无限循环可能会因为内存而停止。但是,在每次迭代中创建一些新的大型对象,则最终会由于内存限制异常而停止。


关于您的第二点:只有在对对象进行硬引用时才是正确的(即,不要超出作用域,以便重型对象不会成为垃圾)。 - Ted Hopp
@TedHopp,换句话说,就是在循环范围之外的另一个对象内创建这些对象。 - Gareve

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