【Docker 运维】Java 应用在 Docker 容器中启动报错:`unable to allocate file descriptor table`

容器内执行脚本时报错如下,Java 进程异常退出:

library initialization failed - unable to allocate file descriptor table
 - out of memory
/entrypoint.sh: line 2: 6 Aborted (core dumped) java ...

 

一、根本原因

该问题源于 Java 8 的 JDK Bug(JDK-8150460)

  • Java 8 在启动时,会尝试根据当前系统 ulimit -n 值,预分配文件描述符表的内存块
  • 在现代系统中默认 ulimit -n 值通常为 65535 或更高;
  • 在容器资源受限或配置不当的情况下,native 层内存不足,JVM 启动失败,抛出 unable to allocate file descriptor table

此外还有两个系统环境相关的影响:

  1. 旧版本的 systemd 不支持 LimitNOFILE=infinity 生效
  2. Docker 容器的默认 ulimit 配置可能不足,或者过大触发此问题。

 

二、判断与排查方法

## 1. 确认容器内的 `ulimit` 值
    
docker exec <container_id> ulimit -n


## 2. 检查系统 systemd 版本
systemctl --version

若版本 < 234`infinity` 设置不会生效。


## 3. 确认是否为 Java 8
java -version

 

三、解决方法

1、限制 Docker 容器的文件描述符上限

将容器启动参数中显式设置 ulimit -n

docker run --ulimit nofile=1024:1024 -d -p 8080:8080 your-image

或者在 docker-compose.yml 中配置:

ulimits:
  nofile:
    soft: 1024
    hard: 1024

推荐设置为 8192 以下,如 1024、4096 等。

2、在执行脚本中动态设置ulimit的值

参考:【stackoverflow】Error upon jar execution - unable to allocate file descriptor table

 

3、升级至 Java 11+

此问题在 Java 9+ 已被修复。

 

四、总结

项目推荐做法
问题本质Java 8 + 高 ulimit -n 导致 native 层分配失败
快速修复--ulimit nofile=1024:1024 限制容器文件句柄
永久方案配置 systemd 或升级 JDK
最优解切换 Java 11+,从根源上解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roman_日积跬步-终至千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值