为什么不能在托管环境中测量对象大小?

时间:2015-08-13 14:58:43

标签: java c# memory

因此,stackoverflow中存在一些问题的变体,它们询问如何测量对象的大小(例如this one)。答案指出这一事实,没有太多详细说明,这是不可能的。有人可以解释为什么不可能或为什么测量对象大小没有意义?

2 个答案:

答案 0 :(得分:1)

  
      
  • 很容易获得物体的大小。

  •   
  • 如果对象很大并且我们使用IO流来获取大小,那么获取对象大小可能会有很小的开销。

  •   
  • 如果你必须非常频繁地获得较大物体的大小,你必须要小心。

  •   
     

看看下面的代码。

 import java.io.*;  

    class ObjectData implements Serializable{
        private int id=1;;
        private String name="sunrise76";
        private String city = "Newyork";
        private int dimensitons[] = {20,45,789}; 
    }

    public class ObjectSize{
        public static void main(String args[]){
            try{
            ObjectData data = new ObjectData();
            ByteArrayOutputStream b = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(b);
            oos.writeObject(data);
            System.out.println("Size:"+b.toByteArray().length);
            }catch(Exception err){
                err.printStackTrace();
            }
        }
    }

答案 1 :(得分:1)

我想从你在Java和C#中测量对象大小的标签开始。不太了解C#,因此以下仅适用于Java。

同一个物体的浅层和扣留尺寸之间也存在差异,我想你是在询问浅层尺寸(这是导致扣留尺寸的基础)。

我还解释了您的术语托管环境,您只想知道特定JVM中运行时>中对象的大小(不仅仅是计算查找的大小)在源代码处。)

我的简短回答:

  • 测量对象大小有意义吗?是的,它确实。在内存限制下运行的应用程序的任何开发人员都很高兴知道类布局和对象分配的内存含义。
  • 在托管环境中进行衡量不可能?不它不是。 JVM必须知道其对象的大小,因此必须能够报告对象的大小。如果我们只有办法要求它。

答案很长:

有很多原因导致无法单独从类定义派生对象大小,例如:

  • Java语言规范仅提供原始类型的下行内存要求。 int消耗至少4个字节,但实际大小取决于VM。

  • 不确定语言规范中有关引用大小的内容。是否对JVM中可能的对象数量有任何限制(这会对对象引用的内部存储大小产生影响)?今天的JVM使用4个字节作为参考指针。

  • JVM可以(并且确实)填充对象字节以在某个边界处对齐,这可以扩展对象大小。今天的JVM通常将对象内存对齐为8字节边界。

但是所有这些原因都不适用于使用实际内存布局的JVM运行时,最终允许其分代垃圾收集器推送对象,因此必须能够报告对象大小。

那么我们如何在运行时了解对象大小? 在Java 1.5中,我们得到了java.lang.instrument.Instrumentation#getObjectSize(Object)。 Javadoc说:

  

返回特定于实现的近似量   指定对象占用的存储空间。结果可能包括一些   或者所有对象的开销,因此可用于比较   在实现中但不在实现之间。估计   可能会在单次调用JVM期间发生更改。

用一粒盐阅读,这告诉我有一种合理的方法可以在运行时的一个点内获得对象的确切浅尺寸。