我有一个Java应用程序,它的内存使用情况很奇怪,我注意到内存使用量明显高于最大堆大小("devDependencies": {
"@angular-devkit/build-angular": "0.900.7",
"@angular-devkit/build-optimizer": "0.900.7",
是Xmx
,使用率是800m
)
在此之前的最近更改之一是正在使用的唯一字符串的大量增加,因此我认为也许我在堆外使用了很多内存的许多字符串-这可能吗?
我正在运行Java 11。
编辑:
例如,在this article中提到:
当我们使用new()运算符创建String对象时,它总是在堆内存中创建一个新对象。 另一方面,如果我们使用String文字语法创建对象,例如“ Baeldung”,它可能会从字符串池中返回一个现有对象(如果已经存在)。
给人两个不同的印象-堆和字符串池。
答案 0 :(得分:3)
在JDK中,包含内部字符串的字符串池由两部分组成:
java.lang.String
对象。因此,字符串池同时具有堆上和堆外部分。堆外部分通常较小,但是如果应用程序创建过多的内部字符串,它仍会占用大量额外的内存。
使用Native Memory Tracking查找String表消耗的内存量。
请参见this answer,以查找该进程可能比-Xmx
占用更多内存的其他原因。
答案 1 :(得分:2)
自Java 7开始,字符串池已成为常规堆的一部分(请参见here)。因此,常规堆大小也会限制字符串池的大小。
您应该从那篇文章中学到的是,new String(...)
总是创建一个新的String
对象,该对象不同于以前创建的所有String
对象。对应于字符串文字的String
对象不是这种情况。
我注意到内存消耗明显高于最大堆大小(Xmx为800m,使用率为1.4g)。
对此的解释是,JVM使用多种方式来使用不属于常规堆的内存。这些包括:
malloc
。答案 2 :(得分:-1)
您可以使用https://visualvm.github.io/index.html
分析和检查例如您占用的内存和堆。