Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在哪里可以找到计算java对象大小的证据_Java_Memory_Object_Jvm_Size - Fatal编程技术网

在哪里可以找到计算java对象大小的证据

在哪里可以找到计算java对象大小的证据,java,memory,object,jvm,size,Java,Memory,Object,Jvm,Size,我搜索java对象的大小已经很长时间了,有很多答案,比如,每个人都告诉我java对象的开销大小,以及如何计算出实际大小。但他们怎么知道?我没有从甲骨文官方文件中找到任何证据。这一结论的证据是什么?或者这些数据仅仅来自一些基于实验的猜测 还有一件事。在官方文件中提到,有一种“近似”的方法来测量物体——有人能向我解释一下“近似”是什么意思吗?当它是准确的,当它不是。最好有证据。我认为答案只能是经验性的: Java虚拟机不要求对象具有任何特定的内部结构 对我来说,最好的方法是最脚踏实地的方法,使用 l

我搜索java对象的大小已经很长时间了,有很多答案,比如,每个人都告诉我java对象的开销大小,以及如何计算出实际大小。但他们怎么知道?我没有从甲骨文官方文件中找到任何证据。这一结论的证据是什么?或者这些数据仅仅来自一些基于实验的猜测


还有一件事。在官方文件中提到,有一种“近似”的方法来测量物体——有人能向我解释一下“近似”是什么意思吗?当它是准确的,当它不是。最好有证据。

我认为答案只能是经验性的:

Java虚拟机不要求对象具有任何特定的内部结构


对我来说,最好的方法是最脚踏实地的方法,使用

long memTaken() {
  final Runtime rt = Runtime.getRuntime();
  return rt.totalMemory() - rt.freeMemory();
}
  • 记住首字母
    memtake()
  • 制作一个包含一百万个对象的数组(调整此数字以适合您的堆)
  • 从记忆中减去
    memtake()
  • 在这个过程中可能会有一些暂时的分配,因此您还需要运行GC。
    System.gc()
    没有提供任何保证,但这种方法对我来说一直很有效:

    for (int i = 0; i < 3; i++) { System.gc(); Thread.sleep(50); }
    
    for(inti=0;i<3;i++){System.gc();Thread.sleep(50);}
    
    您必须小心确保这会产生稳定的结果。例如,一种方法是计算几个不同对象计数的内存负载并比较结果。他们给出的内存/实例答案都应该匹配

    我以前建议过这一点,被用于lame解决方案,被建议使用适当的工具等。因此我使用了工具,例如
    jvisualvm
    ——它给出了错误的结果。这种方法从未给我错误的结果

    如何计算出实际尺寸。但他们怎么知道

    根据经验

    我没有从甲骨文官方文件中找到任何证据

    这取决于JVM。对于基于OpenJDK的JVM,32位JVM的头大小与64位JVM不同,因为头包含引用。其他JVM可能也会有所不同

    或者这些数据仅仅来自一些基于实验的猜测

    基本上,是的

    有人能给我解释一下“近似”是什么意思吗

    当你测量一个物体的大小时,它可能意味着许多不同的东西

    • 这个物体有多大?(浅层)
    • 它使用了多少内存?(对象分配是8字节对齐的,即始终是8的倍数)
    • 对象和所有引用的对象使用了多少空间?(深度)
    • 如果它被丢弃,会释放多少空间?(有多少个对象被共享并出现在释放内存的两个片段的中间)
    • 您是否计算堆栈上使用的空间,或堆外内存中使用的空间
    根据您需要知道的内容,您可以有许多不同的答案,因此有一个数字非常有用,该数字大致接近您用于计算的所有数字


    使用Runtime时遇到的问题是TLAB在大数据块中分配了数据。这些大的块可以进一步以多线程的方式分配。缺点是你不能得到准确的内存使用信息

    static long memTaken() {
        final Runtime rt = Runtime.getRuntime();
        return rt.totalMemory() - rt.freeMemory();
    }
    
    public static void main(String... args) {
        long used1 = memTaken();
        Float i = new Float(0);
        long used2 = memTaken();
        System.out.println("new Float(0) used "+(used2 - used1)+" bytes.");
    }
    
    无选项运行

    new Float(0) used 0 bytes.
    
    关闭TLAB,您会看到使用
    -XX:-UseTLAB

    new Float(0) used 336 bytes.
    
    这比您预期的要高得多,因为必须加载类本身。如果首先通过添加到起始点来创建一个浮点实例

    Float j = new Float(1);
    
    你得到

    new Float(0) used 16 bytes
    

    java对象有两种不同的尺寸:浅尺寸和保留尺寸。 对象的浅层大小是其所有字段的大小之和:对于基本体成员是直接的,对于每个非基本体成员是指针的大小(这在32位和64位体系结构之间有所不同)。您可以使用Instrumentation在运行时查找对象的浅尺寸

    保留大小由对象被丢弃时将释放的堆空间定义。 查找对象的保留大小并非易事,主要是因为对象通常由其他对象组成。例如:

    public class Clazz {
    
        public byte[] member;
    
        public static void main(String[] args) {
            byte[] bytes = new byte[128];
            Clazz a = new Clazz();
            Clazz b = new Clazz();
            a.member = bytes;
            b.member = bytes;
        }
    }
    
    a的保留大小是多少?b呢?
    使用探查器计算保留大小(大多数探查器都使用静态堆分析)

    如果您使用
    -XX:-UseTLAB
    关闭TLAB,则第一种方法会产生更精确的结果,否则内存将分配给大数据块中的线程,因此您将看到零差异,然后使用大内存块。我从未实际观察到这种效果,但我不知道为什么不能。我在回答中添加了一个部分,演示了问题和解决方法。如果分配10k或更多对象,TLAB效应会消失吗?这就是我没有观察它的原因。TLAB的粒度是多少?TLAB的大小由JVM调整,可以变化。效果会逐渐消失,但永远不会完全消失例如,我想从一个对象数组中读取值,它进入cpu缓存的大小是多少?我的假设是:浅深度(当操作引用内部对象时,它将是深深度)和8字节对齐。是吗?@dawnstar值得记住的是,Java中不能有对象数组。您可以拥有对对象的引用数组。数组在内存中是连续的,如果同时创建对象,则对象很可能位于数组的旁边。每个对象都有自己的开销。这样做的好处是,您可以丢弃或保留任何对象,而不会弄乱垃圾收集。