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

Jetty线程数超出start.ini配置值的原因及内存疑问

Jetty线程池配置与实际线程数不符问题解答

问题背景

将Java Spring应用部署在Jetty 9.4.8环境中,已在start.ini里把jetty.threadPool.maxThreads设为1000,但通过htop查看线程数约3030,用ps命令统计Jetty线程数达2876,远高于配置上限。同时Jetty占用120/125G内存却未触发OOM。

1. 该统计线程数是否可与maxThreads对比?

不能直接对比。jetty.threadPool.maxThreads控制的只是Jetty核心业务线程池的最大线程数——也就是处理HTTP请求的工作线程数量。而htop或ps统计的是整个JVM进程的所有线程,除了Jetty的业务线程,还包括:

  • JVM自身的后台线程(比如GC线程、JIT编译线程、信号处理线程)
  • Spring框架的内部线程(比如定时任务线程、异步处理线程、事件监听线程)
  • 应用代码自己创建的线程(比如自定义线程池、异步任务线程)
  • Jetty的其他辅助线程(比如acceptor线程、selector线程、连接清理线程等)

2. maxThreads为何未限制线程数量?

因为maxThreads的作用范围有限,它只约束Jetty的主请求处理线程池,管不了其他来源的线程:

  • 如果你在Spring应用里用了@Async、ThreadPoolTaskExecutor这类组件,这些线程不受Jetty线程池配置管控
  • JVM会根据GC策略自动创建多个GC线程(比如Parallel GC会根据CPU核心数生成对应数量的GC线程)
  • Jetty本身除了业务线程池,还有负责监听端口的acceptor线程、处理NIO事件的selector线程,这些都不在maxThreads的管控范围内

3. 现有线程与运行线程数量差距大的原因?

这里的“差距大”是指统计的总线程数远大于maxThreads配置值,核心原因是统计的是进程全量线程,而maxThreads只覆盖Jetty的业务处理线程。另外,还可能存在大量处于WAITING/TIMED_WAITING状态的空闲线程:

  • 比如Spring的异步线程池、自定义线程池里的核心线程,即使没有任务也会保持存活
  • Jetty线程池里的空闲线程也会处于等待状态,直到有新请求进来
  • JVM的一些后台线程平时也处于休眠等待状态,只有特定触发条件才会活跃

4. 大量线程是否影响内存占用?

肯定会影响。每个Java线程都需要占用一定的内存:

  • 线程栈内存:默认每个线程栈大小是1MB(可通过-Xss参数调整),2800个线程光栈内存就占了2.8GB左右
  • 线程的内部数据结构(比如Thread对象、栈帧、本地变量表等)也会占用堆内存
  • 如果线程持有大量对象引用,会导致GC无法回收这些对象,间接增加内存占用

至于未触发OOM,可能是因为:

  • 剩余的5G内存刚好能支撑线程相关内存和其他堆内存的开销
  • 应用的堆内存设置足够大(比如-Xmx设到了120G左右),线程栈内存属于非堆内存,没占用堆的配额
  • 当前大部分线程处于空闲状态,没有持有大量活跃对象,GC能正常回收无用对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:40:25