我使用以下java项目来确定对象的大小 http://sizeof.sourceforge.net/
public class DataClass /*implements Serializable*/{
// private static final long serialVersionUID = 5199373516861766638L;
String name = "GUNJ";
String lastName= "";
// int age = 148888890;
@Override
public String toString() {
return "DataClass{" +
"Name='" + name + '\'' +
", Last Name='" + lastName + '\'' +
", Age=" +
'}';
}
public static void main(String[] args) {
// SizeOf.skipStaticField(true);
// SizeOf.skipFinalField(true);
// SizeOf.skipFlyweightObject(true);
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(new DataClass()))); //this will print the object size in bytes
}
}
我得到如下结果 144Kb,64Kb,72Kb
似乎正在使用Java检测代码
似乎正在使用以下包:java.lang.instrument.Instrumentation
但不确定包的API是以位还是字节返回对象大小。
答案 0 :(得分:1)
这个工具似乎有点过时了。作为替代方案,我可以建议优秀的JOL,现在已经在OpenJDK下发布了。 它甚至比sizeOf更好,并支持许多很酷的功能。 另请查看演示此工具使用情况的Shipilev's blog post。
答案 1 :(得分:0)
您指出的链接指出:
Use the humanReadable() method to get the object size in byte, kilo or mega (if you need giga your in trouble guy!):
所以它似乎没有位。
对于你的第二个问题,我没有答案。我猜String使用的缓冲区大小大于字符串的大小,所以你可以在缓冲区大小增加之前添加几个字符。
答案 2 :(得分:0)
对于这样的小物件,我不相信你会得到像“144Kb,64Kb,72Kb”这样的结果。你很可能得到144.0b
,64.0b
和72.0b
。
page you have linked已经说过没有任何疑惑的余地:
的System.out.println(SizeOf.deepSizeOf()); //这将打印以字节为单位的对象大小
如果您对SizeOf.humanReadable
的含义持怀疑态度,可以省略其调用并直接打印SizeOf.deepSizeOf
的结果。
由于skipStaticField
,skipFinalField
,skipFlyweightObject
是三个标志,因此允许八种组合,但是您只发布了三个结果而没有告诉您使用的组合,因此很难解释结果。特别是,由于String
的实现在Java版本之间发生了变化,因此您没有指定使用过的Java版本。
如果指定了skipFlyweightObject
,则源代码中的文字String
之类的实习String
不计算在内。如果未指定skipFinalField
,则会计算String
的平面对象存储,但忽略其char[]
内容,因为它使用final
字段引用。如果计算了所有char
,则必须考虑大多数实现都有一个对象大小填充,可以在报告对象大小时进行计算。
似乎在Oracle的JVM中,每个对象的对象大小都是八个字节的倍数。因此,在UTF-16
数组的对象大小增加到八个字节的下一个倍数之前,您最多可以添加四个char
个字符。
您可以使用SizeOf.turnOnDebug();
来了解如何计算对象大小。但是你应该始终记住,这样的累积大小可能包括在不同对象图之间共享的对象,因此加起来比实际使用的堆存储大得多。
还要考虑SizeOf
类后端documentation of Instrumentation.getObjectSize
的内容:
返回指定对象占用的存储量的特定于实现的近似值。 结果可能包括对象的部分或全部开销,因此可用于实现中的比较,但不适用于实现之间。在单次调用JVM期间,估计值可能会发生变化。(由我强调)