如何正确地测量堆内存中应该用于创建某种类型的新对象的内存量(让我们以整数为例进行讨论)?
这个值能否在不进行实验的情况下计算出来?在这种情况下有哪些规则?这些规则是否严格指定在某个地方,还是可能因JVM而异?
如何正确地测量堆内存中应该用于创建某种类型的新对象的内存量(让我们以整数为例进行讨论)?
这个值能否在不进行实验的情况下计算出来?在这种情况下有哪些规则?这些规则是否严格指定在某个地方,还是可能因JVM而异?
这可能因JVM而异。
你可能会喜欢Oracle工程师这篇博客文章:
在32位Hotspot JVM中的Java Integer的情况下,32位有效负载(一个Integer.value字段)附带有96个额外的位:一个标记,一个类,一个字的对齐填充,总共为128位。此外,如果世界上有(例如)六个引用指向此整数(线程加堆),这些引用还会占用192位,总计为320位。在64位机器上,目前一切都是两倍大:对象大小达到256位(现在包括96位的填充),其他地方为384位。相比之下,六个未装箱的基本整数副本占用192位。
static
),这样你就可以从应用程序中访问它。
代码从链接中复制:
public class MyAgent {
private static volatile Instrumentation globalInstr;
public static void premain(String args, Instrumentation inst) {
globalInstr = inst;
}
public static long getObjectSize(Object obj) {
if (globalInstr == null)
throw new IllegalStateException("Agent not initted");
return globalInstr.getObjectSize(obj);
}
}
然而,我相信您将能够找到仅对象的大小(不是原始类型,您也不需要找出它们,因为您已经知道它们 :-))
请注意,getObjectSize()方法不包括由传入对象引用的其他对象使用的内存。例如,如果对象A引用对象B,则对象A报告的内存使用情况仅包括引用对象B所需的字节(通常为4个字节),而不是实际对象。
要获取对象的“深度”内存使用计数(即包括“子对象”或“主”对象引用的对象),则可以使用可从this网站下载的Classmexer代理进行beta下载。
在Java中这并不容易实现:sizeof
不存在,而其他替代方案,例如将对象序列化为字节流并查看结果流的长度,在某些情况下(例如字符串)无法正常工作。
但是,可以参考这个相当复杂的实现,使用对象图。