【问题标题】:Predicting Java memory预测 Java 内存
【发布时间】:2012-08-17 16:46:42
【问题描述】:

有没有办法预测我的 Java 程序将占用多少内存?我来自 C++ 背景,我在类上实现了诸如“size_in_bytes()”之类的方法,我可以相当准确地预测我的应用程序的运行时内存占用。现在我在 Java 世界中,这并不容易......有共享的引用、池、不可变对象......但我仍然希望能够在查看之前预测我的内存占用进程大小在顶部。

【问题讨论】:

  • MemoryMeasurer 是一个非常简单的库,可用于测量整个对象图。
  • 请注意,正如我在下面的回答中所说,工作集基本上等于 GC 堆大小 + JVM 开销,无论您拥有多少大小的对象。

标签: java jakarta-ee memory memory-management


【解决方案1】:

如果您使用检测 API,您可以检查对象的大小。使用起来有点棘手——它需要一个“premain”方法和额外的 VM 参数——但网上有很多例子。 “java instrumentation size”应该会为您找到这些。

请注意,默认方法只会为您提供 shallow 大小。除非您避免在构造函数之外进行任何对象构造(这几乎是不可能的),否则周围会有死对象等待被垃圾回收。

但一般来说,如果您对生成的对象数量有很好的控制,您可以使用这些来估计应用程序的内存需求。

【讨论】:

  • 太棒了!它有一个“getObjectSize”方法!正是我想要的。
【解决方案2】:

您无法预测程序将占用的内存量。但是,您可以预测一个对象将花费多少。 编辑 事实证明我几乎完全错了,这篇文档更好地描述了对象的内存使用情况:http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

【讨论】:

  • 对象引用在 64 位 JVM 上可能不仅仅占用 32 位。此外,我认为每个对象的开销在 JVM 实现之间可能会有所不同。
  • @MikeDaniels depens,我认为 Oracle Java 目前对引用使用了某种压缩方法——至少我记得在某个地方看到过这种方法。
  • 64 位 VM 通常在“压缩指针”模式下运行,其中指针仍然仅为 32 位。但是,是的,总的来说可能存在差异。请参阅我的回复 wrt 检测 API。
  • 谷歌“Java 检测 API”。似乎有一种方法可以进行估算。
  • @owlstead(和 Anony-Mousse)谢谢大家,我不知道压缩指针。
【解决方案3】:

一般来说,您可以相当准确地预测给定对象的需求。有一些相对固定的开销,加上对象中的实例字段,加上适量的填充。但随后对象大小至少(在大多数 JVM 上)被四舍五入到 16 字节边界,并且一些 JVM 将某些对象大小四舍五入到更大的边界(以允许使用标准大小的预分配对象帧)。但是对于给定的 JVM,所有这些都是相对固定的。

当然,不同的是垃圾收集所需的开销。一个简单的垃圾收集器需要 100% 的开销(每个分配的字节至少有一个空闲字节),尽管某些“世代”收集器可以在一定程度上改进这一点。但是 GC 需要多少空间很大程度上取决于工作负载(在大多数 JVM 上)。

另一个问题是,当您以相对较低的分配级别运行时(您可能只使用了最大可用堆的 10%),那么垃圾就会累积。它没有被主动引用,但是垃圾位散布在您的活动对象中,因此它占用了工作集。因此,您的工作集往往大致等于您当前的总体垃圾收集堆大小(加上其他系统开销)。

当然,您可以“限制”堆大小,以便以更高的利用率运行,但这会增加垃圾收集的频率(以及在较小程度上降低 GC 的总体成本)。

【讨论】:

    【解决方案4】:

    您可以使用分析器来了解始终在内存中的一组常量对象。然后你应该执行所有的代码路径来检查内存泄漏。 JProfiler 是一个很好的开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 2020-11-09
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 2014-10-29
      相关资源
      最近更新 更多