8 种 Java- 内存溢出之五 -Unable to create new native thread

简介: 8 种 Java- 内存溢出之五 -Unable to create new native thread

5.1 Unable to create new native thread

Java 应用一般是多线程的. 这意味着在用 Java 写的程序 (似乎) 可以在同时做多件事情. 例如 – 即使机器只有一个处理器 – 当你把内容从一个窗口拖动到另一个, 在后台播放的电影不会停止因为您一次执行了几个操作.

思考线程的一种方法是将它们视为可供提交任务的工作人员. 如果你只有一名员工, 他 / 她只能同时做一个任务. 但是当你有一打员工供你差遣, 他们可以同时完成你的几个要求.

现在, 就像在现实世界的员工, 在 JVM 里的线程也需要一些空间来开展他们被传唤去要处理的工作. 当线程数超过了这个内存空间的限制的时候, 我们就会碰到下边的问题:

这个消息:java.lang.OutOfMemoryError: Unable to create new native thread 意味着Java 应用已经达到它可以运行的线程数的上限.

5.2 原因

只要 JVM 向 OS 申请新线程, 你都有机会碰到 java.lang.OutOfMemoryError: Unable to create new native thread. 只要下面的 OS 不能再分配一个新的 native thread, 这个 OutOfMemoryError 会被抛出. 准确的 native thread 限制与对应的平台有关, 因此, 我们推荐通过运行下面的 例子 来找到这个限制. 但是, 通常, 引发 java.lang.OutOfMemoryError: Unable to create new native thread 会经过下列阶段:

  1. 运行在 JVM 里的一个应用请求一个新的 Java 线程
  2. JVM native 代码传递要创建一个新的 native 线程到 OS
  3. OS 尝试创建一个新的 native 线程, 同时需要分配内存给这个线程
  4. OS 将会拒绝本地内存分配, 可能是因为 32-bit Java 进程大小已经耗尽了它的内存地址区域 – 如: 达到了 2-4GB 的进程大小限制 – 或是这个 OS 的虚拟内存已经被耗尽
  5. 抛出 java.lang.OutOfMemoryError: Unable to create new native thread 错误.

5.3 示例

下列例子循环启动和创建新的线程. 当运行这段代码, 操作系统会迅速达到限制, 显示出 java.lang.OutOfMemoryError: Unable to create new native thread 消息.

while (true) {
    new Thread(new Runnable()) {
        public void run() {
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) { }
        }
    }}.start();
}
JAVA

确切的 native thread 限制与平台有关, 如在 Windows, Linux 和 Mac OS X 上测试结果如下:

  • 64-bit Mac OS X 10.9, Java 1.7.0_45 – JVM 在创建 2031 个线程后死掉
  • 64-bit Ubuntu Linux, Java 1.7.0_45 – JVM 在创建 31893 个线程后死掉
  • 64-bit Windows 7, Java 1.7.0_45 – 因为这个 OS 使用了一个不同的线程模型, 在这个平台上似乎没有抛出该错误. 在线程达到 250,000 后, 进程仍然存活, 尽管 swap 区已经使用了 10GB, 同时应用面临非常严重的性能问题.

所以, 在引入一个小测试时前, 确保你知道你的电脑的限制, 来发现什么时候 java.lang.OutOfMemoryError: Unable to create new native thread 会被触发.

5.4 解决方案

有时候, 你可以通过增加 OS 层面的限制来绕过这个 Unable to create new native thread 问题. 例如, 如果你限制了 JVM 在 user space 可以生成的max user processes, 那么你应该检查并尝试增大这个限制:

[root@dev ~]# ulimit -a
core file size          (blocks, -c) 0
--- cut for brevity ---
max user processes              (-u) 1800
SHELL

通常情况下,因为本机达到线程的限制而抛出 OutOfMemoryError 错误提示可能表明有编程错误. 当你的应用生成了上千个线程, 很有可能有些地方出了大问题 – 没有太多的应用程序可以从如此大量的线程中获益(线程过多, 过犹不及)。

解决这个问题的一个办法是做线程快照 (thread dump) 来理解这个场景. 你可能会花费好几天做这个事情. 这时候, 联系我就是最好的方式(@ ̄ー ̄@).

相关文章
|
6天前
|
存储 缓存 监控
Java内存管理:垃圾回收与内存泄漏
【4月更文挑战第16天】本文探讨了Java的内存管理机制,重点在于垃圾回收和内存泄漏。垃圾回收通过标记-清除过程回收无用对象,Java提供了多种GC类型,如Serial、Parallel、CMS和G1。内存泄漏导致内存无法释放,常见原因包括静态集合、监听器、内部类、未关闭资源和缓存。内存泄漏影响性能,可能导致应用崩溃。避免内存泄漏的策略包括代码审查、使用分析工具、合理设计和及时释放资源。理解这些原理对开发高性能Java应用至关重要。
|
10天前
|
存储 Java 编译器
Java内存区域详解
Java内存区域详解
25 0
Java内存区域详解
|
14天前
|
存储 缓存 安全
【企业级理解】高效并发之Java内存模型
【企业级理解】高效并发之Java内存模型
|
16天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
20天前
|
缓存 算法 Java
Java内存管理与调优:释放应用潜能的关键
【4月更文挑战第2天】Java内存管理关乎性能与稳定性。理解JVM内存结构,如堆和栈,是优化基础。内存泄漏是常见问题,需谨慎管理对象生命周期,并使用工具如VisualVM检测。有效字符串处理、选择合适数据结构和算法能提升效率。垃圾回收自动回收内存,但策略调整影响性能,如选择不同类型的垃圾回收器。其他优化包括调整堆大小、使用对象池和缓存。掌握这些技巧,开发者能优化应用,提升系统性能。
|
21天前
|
Java
java中jar启动设置内存大小java -jar 设置堆栈内存大小
java中jar启动设置内存大小java -jar 设置堆栈内存大小
11 1
|
21天前
|
缓存 算法 Java
Java内存管理:优化性能和避免内存泄漏的关键技巧
综上所述,通过合适的数据结构选择、资源释放、对象复用、引用管理等技巧,可以优化Java程序的性能并避免内存泄漏问题。
25 5
|
24天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
64 0
|
24天前
|
监控 网络协议 NoSQL
java线上排查OOM内存溢出
java线上排查OOM内存溢出
22 0
|
26天前
|
存储 Linux C语言
【C++练级之路】【Lv.5】动态内存管理(都2023年了,不会有人还不知道new吧?)
【C++练级之路】【Lv.5】动态内存管理(都2023年了,不会有人还不知道new吧?)