【问题标题】:Why my Java heap is with so many char[]为什么我的 Java 堆有这么多 char[]
【发布时间】:2013-12-21 16:33:41
【问题描述】:

我在 Tomcat 中有一个 Web 应用程序,我在其中执行许多字符串操作(子字符串、索引、修剪等)。我用 jmap 做了一个堆转储,然后用 VisualVM 加载了它,我意识到我的堆内存使用量的近 50% 是用 char[], 为什么 char[] 占用了内存?我应该担心吗?它与字符串池有关吗?

【问题讨论】:

  • 我们能看到一些代码吗?看起来您正在使用大量字符串 - 您是否检查了 gc() 之后的结果?
  • 这样的事情: return tiempo.replace("años", "").replace("año", "") .replace("meses", "").replace("mes" , "") .replace("semanas", "").replace("semana", "") .replace("dias", "").replace("dia", "").trim();
  • @NestorHernandezLoli 这将创建许多立即超出范围的临时对象。那里没有内存泄漏,垃圾收集器还没有清理它们。
  • @NestorHernandezLoli 从截图中我们可以看到你有很多哈希映射条目。您是否将字符串存储到地图中?
  • @Andrey Chaschev,不,对于这个类,我没有使用 HashMaps 来保存字符串

标签: java performance tomcat memory-leaks


【解决方案1】:

字符串在内部只是一个 char[] 和一些额外的数据。 char[] 表示字符数组,换句话说,它是一个按字符保存字符串的数组。如果您进行大量字符串处理,则您的系统完全有可能使用 char 数组。

所以简而言之,除非您的系统实际上使用了更多的内存,否则无需担心。在这种情况下,您可以查看是否有一些文件结构未清除(哈希映射或相关)。

【讨论】:

  • 请注意,profiler 只显示大约 90M 在使用中;这一点也不多,垃圾收集器可能还没有足够的兴趣来清理它们。
  • 那么 char[] 是否有资格进行垃圾回收?
  • char[]s 如果你用完了它们可以被收集。问题是您是否估计系统内应该有多少字符串?如果您希望有大约 1000 个字符串并且您有 100 000+,那么有些问题是错误的,但是如果您希望有这么多,那么有些问题是错误的。那么你估计有多少根弦呢?
【解决方案2】:

char[] 的 811k 对应于 Strings 的 800k,所以是的,你的字符串太多了。

如果您遇到内存泄漏(根据标签判断),那么很可能是HashMap 中的字符串。你有 800k 个字符串实例,200k 个哈希条目实例,30k 个映射。这可能意味着您的字符串保存在此缓存中并且不会被删除。全局映射是内存泄漏的常见原因,需要确保将它们从缓存中清除。

由于所有这些值都没有经过 GC 处理,您可以尝试使用 JProfiler 之类的工具分析对象图,看看是什么持有它们。

【讨论】:

  • 800k 不算多。如何量化“字符串过多”?
  • @SteveKuo by Nestor 仅对此有问题。 :-) 当它还没有 OOM 时,这可能是一个状态的转储,但很快就会。我的回答是猜测,只是我见过很多这样的案例,我对此很有信心。
猜你喜欢
  • 1970-01-01
  • 2013-11-08
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2012-12-24
  • 1970-01-01
相关资源
最近更新 更多