You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java无限循环按Ctrl+C时try块语句重复执行原因排查

问题根本原因

首先要澄清一个常见误解:你在程序等待输入时按Ctrl+C触发NoSuchElementException,并不是JVM收到了进程终止信号(SIGINT)。默认配置下JVM收到SIGINT会直接终止进程,根本不会执行你写的catch块逻辑。你能走到异常分支,是因为终端在规范输入模式下,优先把Ctrl+C解释为「中断当前阻塞的读输入操作」,让System.in输入流返回中断/结束状态,而不是直接把信号发给JVM杀进程。

重复输出的核心诱因是两个逻辑问题叠加,既不是Java语言本身的机制缺陷,也不是Scanner类的bug:

  • 第一,你写的for(;;)是没有任何退出条件的无限循环,catch块里没有加break时,捕获异常、打印完退出提示后,程序根本不会终止,会立刻进入下一轮循环。
  • 第二,Scanner在输入流被中断、到达EOF状态后,内部会标记「输入源已耗尽」,后续再调用next()等读取方法时,不会再阻塞等待用户输入,会立刻抛出NoSuchElementException。

这两个问题叠加后,流程就变成了:

  1. 第一次按Ctrl+C,阻塞的sc.next()被中断抛出异常,进入catch块打印第一遍退出提示
  2. 因为没有break,循环回到开头,先打印Enter a word: ,再调用sc.next()
  3. 此时Scanner已经处于输入耗尽状态,立刻第二次抛出异常,进入catch块打印第二遍退出提示
  4. 上述流程会快速循环重复,直到输出缓冲区刷新、或者JVM真正被终止信号杀死,你就会看到2次甚至多次重复的打印内容。

你在catch块加上break之后,第一次捕获到异常就会直接跳出无限循环,main方法执行完程序正常退出,自然不会再触发后续的重复异常和打印,问题就消失了。

补充验证点:你可以在catch块里加一行打印异常堆栈的代码,会发现重复触发的异常栈完全一致,都是sc.next()调用抛出的,不存在什么信号处理重复触发的问题。如果在程序没有等待输入的时机按Ctrl+C,JVM会直接收到SIGINT终止进程,根本不会执行你catch块里的打印逻辑。

内容的提问来源于stack exchange,提问作者imraklr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.11 16:16:22