问题处理记录与深入:系统线程耗尽,Java无法调用native方法新建线程

news2025/1/21 13:00:37

1. 问题处理记录

1.1 问题描述

  • 公司使用Presto作为OLAP查询引擎,Presto的coordinator节点在运行过程中报错

    java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
          at java.base/java.lang.Thread.start0(Native Method)
          at java.base/java.lang.Thread.start(Thread.java:802)
    
  • 当时,第一反应:有了异常堆栈,大概知道是哪里发生了线程滥用,这是测试环境,先立马重启服务后观察下线程增长情况

  • 重启服务后,不停执行如下命令,发现对应Java进程的线程使用量确实再不断增加

cat /proc/${pid}/status | grep "Threads"

1.2 问题修复与观察

  • 问题原因: 通过异常堆栈,发现是某个方法不停新建HttpClient、却又没有进行close导致

  • 问题修复后,通过如下shell脚本观察线程使用情况:每隔10min打印一次线程数

    #!/bin/bash
    
    while true
    do
        echo -ne $(date +%Y-%m-%dT%H:%M:%S)" "
        cat /proc/${pid}/status | grep "Threads" # 使用时,${pid}替换成对应的Java服务进程号
        sleep 10m
    done
    
  • 定时执行shell脚本,发现线程数得到了控制,观察4小时,最大线程数699 —— 问题成功修复

    nohup ./watch_threads.sh > threads_stat.txt 2>&1 &
    

    在这里插入图片描述

2. 疑问:一个Java进程究竟能创建多少线程?

  • 后来,使用ulimit -a查看系统资源配置时,发现系统允许root用户可以创建的最大进程或线程数为unlimited

  • 因此,笔者有了疑惑:

    • 既然是unlimited,为何会出现unable to create native thread的情况?
    • 还有,从系统资源有限的角度来说,这里的unlimited不应该是无上限,而是相对具体的、类似65636这样的固定值来说,只要系统资源未耗尽就可以创建线程
  • 可惜的是,笔者当时并未查看报错时的线程数,无法判断这个unlimited的上限究竟是多少

2.1 优秀文章的启发:How Many Threads Can a Java VM Support?

  • Baeldung的一篇文章:How Many Threads Can a Java VM Support?,让笔者大概有了一个认识
  • JVM,即一个Java进程,能创建的最大线程数,至少有两个方面的决定因素:
    • JVM本身 + 系统内存
    • 操作系统限制

2.2 决定因素1:JVM本身 + 系统内存

  • JVM中,堆栈的max size由-Xss-XX:ThreadStackSize进行设置
    -Xss1024k # 如果省略unit,默认unit:Byte
    -XX:ThreadStackSize=1024 # unit:KB
    
  • JVM会为每个线程创建自己的堆栈,创建堆栈使用的内存为系统内存,并非JVM Heap memory
  • 因此,有如下计算公式
    • MaxProcessMemory:是指进程的最大寻址空间
    • ReservedOsMemory:保留的操作系统内存,如Native Heap、JNI之类,一般100MB
    Number of threads = (MaxProcessMemory - JVMHeapMemory - ReservedOsMemory) / (ThreadStackSize) 
    

2.3 决定因素2:操作系统限制(以Linux系统为例)

  • 首先,Linux系统级对max thread的限制,threads-max

    cat /proc/sys/kernel/threads-max # 服务器上的threads-max = 6179160
    
  • 其次, Linux系统在内核级别将线程视为进程,因此限制最大进程数的pid_max也会影响JVM可以创建的线程数量

  • 这也是为什么ulimit -a展示的max user processes也被视为线程数限制的原因

    cat /proc/sys/kernel/pid_max # 相对threads-max,值更小,4194303
    
  • 还有,vm.max_map_count 参数,它指定进程可以拥有的虚拟内存区域 (VMAs,Virtual Memory Areas) 的最大数量

    cat /proc/sys/vm/max_map_count # 三者中,max_map_count的值最小,2097152
    
  • 最后,Linux支持针用户级别的资源限制,可以通过ulimit -a查看当前用户的资源限制。其中,max user processes的值也限制了JVM能创建的最大线程数

2.4 总结

  • JVM能创建的最大线程数是由各种因素综合决定的,且一定是这些因素中的min value决定
  • 决定因素1触发unable to create native thread,其根因是内存不足
  • 决定因素2中触发unable to create native thread,其本质是系统资源限制

3. 后记

  • 后续,如果有机会可以学习:
    • 如何触发unable to create native thread
    • 如何调整JVM参数、Linux系统的线程limit,从而验证这些影响因素
  • 一些优秀参考链接:
    • 启蒙文章:How Many Threads Can a Java VM Support?
    • unable to create new native thread 问题处理,指出了该出现错误的两种原因:内存不足达到线程数限制
    • Maximum Number of Threads per Process in Linux
    • How to Get the Number of Threads in a Java Process,可以学习如何通过ps命令查看线程数
    • 非常简单的触发unable to create native thread错误的demo:java jvm 最大线程数设置
    • 对决定因素1中计算公式的介绍:JVM最多能创建多少个线程: unable to create new native thread

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1880478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用Roofline模型去分析pytorch和Triton算子

用Roofline模型去分析pytorch和Triton算子 1.参考链接2.测试环境3.安装相关依赖4.锁频5.获取理论算力6.创建测试脚本7.运行测试程序生成Roofline图8.NVIDIA Nsight Compute生成Roofline9.效果图A.nn.LinearB.Triton实现 本文演示了如何用Roofline模型去分析pytorch和Triton算子…

Mx Admin 基于react18的后台管理系统

前言 Mx Admin 基于React18 vite5 antd5的后台管理系统, 基于RBAC的权限控制系统,动态菜单和动态路由支持tab路由缓存嵌套菜单支持多种菜单布局模式亮暗色主题切换

AttGAN实验复现 2024

AttnGAN 代码复现 2024 文章目录 AttnGAN 代码复现 2024简介环境python 依赖数据集TrainingPre-train DAMSMTrain AttnGAN SamplingB_VALIDATION 为 False (默认)B_VALIDATION 为 True 参考博客 简介 论文地址: https://arxiv.org/pdf/1711.10485.pdf 代码 python…

Unity实现简单的MVC架构

文章目录 前言MVC基本概念示例流程图效果预览后话 前言 在Unity中,MVC(Model-View-Controller)框架是一种架构模式,用于分离游戏的逻辑、数据和用户界面。MVC模式可以帮助开发者更好地管理代码结构,提高代码的可维护性…

【web】2、集成插件

1、element-plus 官网地址:设计 | Element Plus 安装 plus 及 icon 图标库 1.1 官网提供plus安装方法: 1.2 官网提供 icon 安装方法 1.3 安装 pnpm install element-plus element-plus/icons-vue main.ts全局安装element-plus,element-plus默认支持语言英语设…

isspace()方法——判断字符串是否只由空格组成

自学python如何成为大佬(目录): https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 isspace()方法用于判断字符串是否只由空格组成。isspace()方法的语法格式如下: str.isspace() 如果字符串中只包含空格&…

深度学习基准模型Mamba

深度学习基准模型Mamba Mamba(英文直译:眼镜蛇)具有选择性状态空间的线性时间序列建模,是一种先进的状态空间模型 (SSM),专为高效处理复杂的数据密集型序列而设计。 Mamba是一种深度学习基准模型,专为处理长序列数据而设计&…

ONLYOFFICE 8.1 版本桌面编辑器测评

在现代办公环境中,办公软件的重要性不言而喻。从文档处理到电子表格分析,再到演示文稿制作,强大且高效的办公软件工具能够极大提升工作效率。ONLYOFFICE 作为一个功能全面且开源的办公软件套件,一直以来都受到广大用户的关注与喜爱…

C++:typeid4种cast转换

typeid typeid typeid是C标准库中提供的一种运算符,它用于获取类型的信息。它主要用于类型检查和动态类型识别。当你对一个变量或对象使用typeid运算符时,它会返回一个指向std::type_info类型的指针,这个信息包含了关于该类型名称、大小、基…

C#进阶-ASP.NET WebForms调用ASMX的WebService接口

ASMX 文件在 ASP.NET WebForms 中提供了创建 Web 服务的便捷方式,通过公开 Web 方法,允许远程客户端调用这些方法并获取数据。本文介绍了 ASMX 文件的基本功能、如何定义 WebService 接口、通过 HTTP 和 SOAP 请求调用 WebService 接口,以及使…

python实现网页自动化(自动登录需要验证的网页)

引言: python作为实现网页自动化的一个重要工具,其强大的各种封装的库使得程序运行更加简洁,只需要下载相应的库,然后调用库中的函数就可以简便的实现我们想要的网页相关操作。 正文: 我的前几篇文章写了关于初学爬虫中比较容易上手的功能,例如爬取静态网页的数据、动…

系统运维面试总结(shell编程)

SYNDDOS攻击,需要判断这个访问是正常访问还是信包攻击,当前这个信包发起的访问数量是多少,例如看到30个信包同时再访问时设置监控报警。

Wails 安装初体验

文章目录 Wails 安装说明1. 系统要求2. 安装步骤3. 构建应用 结论 Wails 安装说明 Wails 是一个用于构建桌面应用的 Go 框架,结合了现代前端技术。以下是安装步骤: 1. 系统要求 Go 1.16 或更高版本Node.js 和 npm可选:适用于 Windows、mac…

SSH版本升级-openssh-9.7p1

SSH版本升级-openssh-9.7p1 1、查看当前版本2、安装openssl2.1、编译安装ssl 3、下载新版本SSH4、备份原有的SSH配置5、上传文件并解压6、卸载原有的openssh包7、编译安装openssh7.1、在解压后的目录,初始化openssh7.2、将文件拷回7.3、修改配置文件 最终实现&#…

傻瓜交换机多网段互通组网、设备无法配置网关案例

记录一下: 一、傻瓜交换机多网段互通组网 1、客户在核心交换机上创建了VLAN10,VLAN20。 VLAN10:IP192.168.10.254 VLAN20:IP192.168.20.254 在核心交换机下挂了一台傻瓜交换机,傻瓜交换机接入了一台OA服务器IP&#…

Qt之Pdb生成及Dump崩溃文件生成与调试(含注释和源码)

文章目录 一、Pdb生成及Dump文件使用示例图1.Pdb文件生成2.Dump文件调试3.参数不全Pdb生成的Dump文件调试 二、个人理解1.生成Pdb文件的方式2.Dump文件不生产的情况 三、源码Pro文件mian.cppMainWindowUi文件 总结 一、Pdb生成及Dump文件使用示例图 1.Pdb文件生成 下图先通过…

Transformer详解encoder

目录 1. Input Embedding 2. Positional Encoding 3. Multi-Head Attention 4. Add & Norm 5. Feedforward Add & Norm 6.代码展示 (1)layer_norm (2)encoder_layer1 最近刚好梳理了下transformer,今…

深入理解PHP命名空间

在PHP项目中,命名空间(namespace)是一个非常重要的特性。它不仅帮助开发者组织代码,还能避免类、函数、常量等命名冲突问题。本文将详细介绍PHP命名空间的概念、使用方法和最佳实践。 一、什么是命名空间? 命名空间…

LeetCode:经典题之2、445 题解及延伸

系列目录 88.合并两个有序数组 52.螺旋数组 567.字符串的排列 643.子数组最大平均数 150.逆波兰表达式 61.旋转链表 160.相交链表 83.删除排序链表中的重复元素 389.找不同 1491.去掉最低工资和最高工资后的工资平均值 896.单调序列 206.反转链表 92.反转链表II 141.环形链表 …

github主页这样优化,让人眼前一亮

我的主页(一之十六) 1. 创建与账户ID同名的仓库 注意:记得勾选Add a README file 2. markdown语法自定义README.md 3. 辅助工具 优秀profile:https://zzetao.github.io/awesome-github-profile/动态文字:https://r…