2

可能重复:
在 Java 中,确定对象大小的最佳方法是什么?

假设您有一个允许您向其中添加数据的数据结构,例如一个列表:

List<KeyValuePair>

由于系统的客户端实际上添加了内容......在某些时候,JVM会耗尽内存,这只是何时发生的问题。定期将包含此列表的对象保存到磁盘和gc其余部分会很好。

使用 Java,是否可以估计一个对象现在占用了多少内存?

4

3 回答 3

3

getObjectSize()方法可能是您正在寻找的。来自Interface Instrumentation文档
的引用:

getObjectSize(Object objectToSize)
返回指定对象消耗的存储量的特定于实现的近似值。

于 2012-06-28T20:26:47.507 回答
3

你正在寻找java.lang.instrument.Instrumentation.getObjectSize(Object object)

文档:

返回指定对象消耗的存储量的特定于实现的近似值。结果可能包括对象的部分或全部开销,因此对于实现内的比较有用,而不是实现之间的比较。估计值可能会在 JVM 的单次调用期间发生变化。

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/instrument/Instrumentation.html#getObjectSize%28java.lang.Object%29

但为了能够使用它:

访问 Instrumentation 接口实例的唯一方法是以指示代理类的方式启动 JVM - 请参阅包规范。Instrumentation 实例被传递给代理类的 premain 方法。一旦代理获得了 Instrumentation 实例,代理就可以随时调用实例上的方法。

良好的实现示例: http ://www.javalobby.org/java/forums/t19309.html

于 2012-06-28T20:30:07.493 回答
1

您可以通过制作许多相同的对象并测量所占用的内存来做到这一点。我现在已经多次使用这种技术,结果稳定、可重复。在大纲中,

public static void main(String[] args) {
  final Object[] a = new Object[10000];
  final long startMem = memTaken();
  for (int i = 0; i < a.length; i++) a[i] = new Object();
  System.out.println((memTaken() - startMem) / a.length);
  a.hashCode();
}
static long memTaken() {
  final Runtime rt = getRuntime();
  try {
    rt.gc(); Thread.sleep(50);
    rt.gc(); Thread.sleep(50);
  } catch (InterruptedException e) {}
  final long memTaken = rt.totalMemory() - rt.freeMemory();
  System.out.println("Mem taken " + memTaken);
  return memTaken;
}

这可靠地在我的机器上产生了数字 24。这种方法的优点是它会自动考虑对象的有效堆影响,并考虑所有因素。当然,在信任它之前,您应该检查它在您的设置中是否可靠。

于 2012-06-28T21:05:48.253 回答