【问题标题】:Is the string pool size affected by setting max heap size?设置最大堆大小是否会影响字符串池大小?
【发布时间】:2020-04-05 12:59:34
【问题描述】:

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

在此之前的最近更改之一是使用的唯一字符串大量增加,所以我想我可能有很多字符串在堆外使用了大量内存 - 这可能吗?

我正在运行 java 11。

编辑:

例如,在this article 中提到:

当我们使用 new() 操作符创建一个 String 对象时,它总是在堆内存中创建一个新对象。 另一方面,如果我们使用字符串字面量语法创建一个对象,例如“Baeldung”,如果它已经存在,它可能会从字符串池中返回一个现有对象。

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

【问题讨论】:

    标签: java string memory jvm java-11


    【解决方案1】:

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

    1. 哈希表,在堆外分配并包含对实习字符串的引用。此内存区域在本机内存跟踪报告中显示为“字符串表”。
    2. 实习字符串内容。这些是 Java 堆中的常规 java.lang.String 对象。

    因此,字符串池同时具有堆内和堆外部分。堆外部分通常更小,但如果应用程序创建过多的内部字符串,它仍会占用大量额外内存。

    使用Native Memory Tracking 查找String 表消耗的内存量。

    请参阅this answer,了解进程占用内存比-Xmx 多得多的其他原因。

    【讨论】:

    • 我明天会看看这个,但它看起来很棒!非常喜欢!
    • 我支持安德烈对这个问题的回答,这非常有用:stackoverflow.com/questions/53451103/…
    • 接受,这是一个很棒的答案。解释主要问题,建议如何验证,并对潜在问题提出建议
    【解决方案2】:

    从 Java 7 开始,字符串池一直是常规堆的一部分(请参阅here)。所以常规堆大小也约束了字符串池的大小。

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

    我注意到内存消耗明显高于最大堆大小(Xmx 为 800m,使用量为 1.4g)。

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

    • JVM 可执行文件及其共享库的内存
    • 用于应用程序加载的本机代码库的内存
    • 用于 Java 线程堆栈的内存段
    • 用于表示元空间的内存...保存 JIT 编译的本机代码等,
    • 本机代码分配的“本机”堆中的内存;例如使用malloc
    • 为直接缓冲区分配的内存

    【讨论】:

    • 请回答!你能链接到任何官方文档吗?
    • 我的记忆有问题。字符串池在 Java 7 而不是 Java 8 中移至常规堆。
    • Ty 的链接,我会看一下。关于您的答案的补充,我知道 JVM 和外部内存的其他部分,但我很难相信 600m 或更多在堆外用于这些 klind 的事情。
    • 相信它。 (也许您不知道您的应用程序及其依赖库在幕后做什么。)
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      • 2019-08-03
      • 1970-01-01
      相关资源
      最近更新 更多