设置最大堆大小是否会影响字符串池大小?

Is the string pool size affected by setting max heap size?

我有一个 java 应用程序,它的内存使用情况很奇怪,我注意到内存消耗明显高于最大堆大小(Xmx800m,使用量是1.4g).

在此之前最近发生的变化之一是使用的唯一字符串大幅增加,所以我想也许我使用的许多字符串在堆外使用了大量内存 - 这可能吗?

我 运行 java 11.

编辑:

例如,在this article中提到:

When we create a String object using the new() operator, it always creates a new object in heap memory. On the other hand, if we create an object using String literal syntax e.g. “Baeldung”, it may return an existing object from the String pool, if it already exists.

给人的印象是 2 个不同的区域 - 堆和字符串池。

您可以使用https://visualvm.github.io/index.html来分析和检查例如您占用的内存和堆。

从 Java 7 开始,字符串池就成为常规堆的一部分(参见 here)。所以常规堆大小也限制了字符串池的大小。

您应该从那篇文章中得到的真实信息是 new String(...) 总是会创建一个新的 String 对象,该对象不同于所有先前创建的 String 对象。对于对应于字符串文字的 String 对象,情况并非如此。

I noticed that the memory consumption is significantly higher than the max heap size (Xmx is 800m, usage is 1.4g).

对此的解释是,JVM 可以通过多种方式使用不属于常规堆的内存。其中包括:

  • JVM 可执行文件及其共享库的内存
  • 用于应用程序加载的本机代码库的内存
  • 用于Java线程堆栈的内存段
  • memory used to represent the metaspace ... 保存 JIT 编译本机代码等,
  • 本机代码分配的 "native" 堆中的内存;例如使用 malloc.
  • 分配给直接缓冲区的内存

在JDK中,包含interned字符串的字符串池,由两部分组成:

  1. 散列table,它是在堆外分配的,包含对驻留字符串的引用。此内存区域在本机内存跟踪报告中显示为 "String table"。
  2. 驻留的字符串内容。这些是 Java 堆中的常规 java.lang.String 对象。

因此,字符串池既有堆内部分,也有堆外部分。堆外部分通常较小,但如果应用程序创建过多的驻留字符串,它仍然会占用大量额外内存。

使用Native Memory Tracking查找字符串table消耗的内存量。

请参阅 以查找进程可能比 -Xmx 占用更多内存的其他原因。