有没有办法预测我的 Java 程序将占用多少内存?我来自 C++ 背景,我在类上实现了诸如“size_in_bytes()”之类的方法,我可以相当准确地预测我的应用程序的运行时内存占用。现在我在一个 Java 世界中,这并不容易......有共享的引用、池、不可变对象......但我仍然希望能够在查看之前预测我的内存占用进程大小在顶部。
4 回答
如果您使用检测 API,则可以检查对象的大小。使用起来有点棘手——它需要一个“premain”方法和额外的 VM 参数——但网上有很多例子。“ java instrumentation size ”应该可以找到这些。
请注意,默认方法只会给你一个浅尺寸。除非您避免在构造函数之外进行任何对象构造(这几乎是不可能的),否则周围会有死对象等待垃圾收集。
但总的来说,如果您对生成的对象数量有很好的控制,您可以使用这些来估计应用程序的内存需求。
您无法预测程序将占用的内存量。但是,您可以预测一个对象将花费多少。编辑结果我几乎完全错了,这个文档更好地描述了对象的内存使用:http ://www.javamex.com/tutorials/memory/object_memory_usage.shtml
一般来说,您可以相当准确地预测给定对象将需要什么。有一些相对固定的开销,加上对象中的实例字段,加上适量的填充。但是随后对象大小被四舍五入到至少(在大多数 JVM 上)16 字节的边界,并且一些 JVM 将某些对象大小四舍五入到更大的边界(以允许使用标准大小的预分配对象帧)。但是对于给定的 JVM,所有这些都是相对固定的。
当然,不同的是垃圾收集所需的开销。一个简单的垃圾收集器需要 100% 的开销(每个分配的字节至少有一个空闲字节),尽管某些种类的“世代”收集器可以在一定程度上改进这一点。但是 GC 需要多少空间很大程度上取决于工作负载(在大多数 JVM 上)。
另一个问题是,当您以相对较低的分配级别运行时(您可能只使用了最大可用堆的 10%),那么垃圾就会积累。它没有被主动引用,但是垃圾位散布在您的活动对象中,因此它占用了工作集。因此,您的工作集往往大致等于您当前的总体垃圾收集堆大小(加上其他系统开销)。
当然,您可以“限制”堆大小,以便以更高的利用率运行,但这会增加垃圾收集的频率(以及较小程度的 GC 总成本)。
您可以使用分析器来了解始终在内存中的一组常量对象。然后你应该执行所有的代码路径来检查内存泄漏。JProfiler是一个很好的入门工具。