Java 线程占用多少内存?

JVM 不会主动将提交内存的大小调整为线程数 * 1MB,这是一个错误的假设,基于错误的 NMT 报告,在 Java 8 中,提交内存会自动设置为保留内存。请参阅 https://bugs.openjdk.java.net/browse/JDK-8191369

提交的内存由堆栈深度定义。感谢托马斯·斯图夫(Thomas Stuefe)在评论中指出这一事实。

所有 Java 线程占用的内存是应用程序总内存消耗的重要组成部分。有几种技术可以限制创建的线程数,具体取决于应用程序是受 CPU 限制还是受 IO 限制。如果您的应用程序是 IO 绑定的,则很可能需要创建一个线程池,其中包含大量线程,这些线程可以绑定到某些 IO 操作(处于阻塞/等待状态、从数据库读取、发送 HTTP 请求)。

但是,如果您的应用程序宁愿将时间花在某些计算任务上,例如,您可以使用线程数较少的 HTTP 服务器(例如 Netty)并节省大量内存。让我们看一个示例,说明我们需要牺牲多少内存来创建新线程。

线程内存包含堆栈帧、局部变量、方法参数…线程大小可以以这种方式配置默认值(以千字节为单位):

$ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize  
     intx CompilerThreadStackSize    = 1024  {pd product} {default}
     intx ThreadStackSize            = 1024  {pd product} {default}
     intx VMThreadStackSize          = 1024  {pd product} {default}

Java 8 上的线程内存消耗

$ java -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary /
-XX:+PrintNMTStatistics -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)

Native Memory Tracking:

Total: reserved=6621614KB, committed=545166KB
-                 Java Heap (reserved=5079040KB, committed=317440KB)
                            (mmap: reserved=5079040KB, committed=317440KB) 

-                     Class (reserved=1066074KB, committed=13786KB)
                            (classes #345)
                            (malloc=9306KB #126) 
                            (mmap: reserved=1056768KB, committed=4480KB) 

-                    Thread (reserved=19553KB, committed=19553KB)
                            (thread #19)
                            (stack: reserved=19472KB, committed=19472KB)
                            (malloc=59KB #105) 
                            (arena=22KB #34)

我们可以看到两种类型的内存:

保留 — 主机的操作系统保证可用的大小(但仍未分配且无法被 JVM 访问) — 这只是一个承诺
已提交 — 已由 JVM 获取、可访问和分配
在 Thread 部分中,我们可以在 Reserved 和 Committed 内存中发现相同的数字,它非常接近线程数 * 1MB。原因是 JVM 从一开始就积极地为线程分配最大可用内存。

Java 11 上的线程内存消耗

$ java -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary /
-XX:+PrintNMTStatistics -version 
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)

Native Memory Tracking:

Total: reserved=6643041KB, committed=397465KB
-                 Java Heap (reserved=5079040KB, committed=317440KB)
                            (mmap: reserved=5079040KB, committed=317440KB) 

-                     Class (reserved=1056864KB, committed=4576KB)
                            (classes #426)
                            (  instance classes #364, array classes #62)
                            (malloc=96KB #455) 
                            (mmap: reserved=1056768KB, committed=4480KB) 
                            (  Metadata:   )
                            (    reserved=8192KB, committed=4096KB)
                            (    used=2849KB)
                            (    free=1247KB)
                            (    waste=0KB =0,00%)
                            (  Class space:)
                            (    reserved=1048576KB, committed=384KB)
                            (    used=270KB)
                            (    free=114KB)
                            (    waste=0KB =0,00%)

-                    Thread (reserved=15461KB, committed=613KB)
                            (thread #15)
                            (stack: reserved=15392KB, committed=544KB)
                            (malloc=52KB #84) 
                            (arena=18KB #28)

您可能会注意到,我们节省了大量内存,只是因为我们使用的是 Java 11,它在线程创建时不再主动分配给保留内存。当然,这只是 java 版本命令,但如果你尝试一下,你一定会注意到一个很大的改进。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值