8 年开发架构师浅析 SpringBoot 的 JVM 的内存占用与 Docker-spring
JVM 的非堆内存分为几个不同的区域。我们可以使用 HotSpot VM 的本机内存跟踪(NMT)来检查这些区域的内存使用情况。请注意,虽然 NMT 不跟踪所有原生本机 Native 内存使用情况(例如,它不跟踪第三方本机代码内存分配),但对于大类典型的 Spring 应用程序来说已经足够了。可以通过启动应用程序-XX:NativeMemoryTracking=summary 然后使用 jcmd VM.native_memory summary 来显示内存使用情况摘要来使用 NMT 。
让我们通过查看应用程序来说明 NMT 的使用,在这种情况下,我们的老朋友 Petclinic。下面的饼图显示了当使用 48MB 最大堆(-Xmx48M)启动 Petclinic 时由 NMT 报告的 JVM 的内存使用量(减去其自身的开销):
正如您所看到的,非堆内存占绝大多数 JVM 的内存使用量,堆内存仅占总数的六分之一。在这种情况下,大约 44MB(垃圾收集后立即使用 33MB)。非堆内存使用总量为 223MB。
[](()本机 Native 内存区域
压缩类空间:用于存储有关已加载的类的信息。受到约束 MaxMetaspaceSize。已加载的类数的函数。
线程:JVM 中线程使用的内存。正在运行的线程数的函数。
代码缓存:JIT 用于存储其输出的内存。已加载的类数的函数 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 。受到约束 ReservedCodeCacheSize。可以通过调整 JIT 来减少,例如,禁用分层编译。
GC:存储 GC 使用的数据。根据使用的垃圾收集器而有所不同。
符号:存储符号,如字段名称,方法签名和实习字符串。过多的符号内存使用情况可能表明字符串过于激进。
内部:存储不适合任何其他区域的其他内部数据。
[](()非堆内存与堆内存的不同
与堆内存相比,非堆内存在负载下不太可能发生变化。一旦应用程序加载了它将使用的所有类并且 JIT 完全预热,事情就会陷入稳定状态。要查看压缩类空间使用量的减少,加载类的类加载器需要进行垃圾回收。在将应用程序部署到 servlet 容器或应用程序服务器时,这种情况更常见 - 应用程序的类加载器将在取消部署应用程序时进行垃圾收集 - 但现代应用程序部署方法很少发生。
[](()调整 JVM 的大小
配置 JVM 以有效利用给定数量的可用 RAM 并不容易。如果您启动 JVM -Xmx16M 并期望它最多可以使用 16MB 的 RAM,那么您会感到非常惊讶。
调整 JVM 大小的一个有趣的方面是 JIT 的代码缓存。默认情况下,HotSpot JVM 最多可使用 240MB。如果代码缓存太小,JIT 将耗尽空间来存储其输出,因此性能将受到影响。如果缓存太大,可能会浪费内存。在调整代码缓存大小时,查看应用程序内存使用情况及其性能的影响非常重要。
评论