【问题标题】:How many bytes of memory does a java.util.Date object use?java.util.Date 对象使用多少字节的内存?
【发布时间】:2011-01-13 15:46:33
【问题描述】:

我需要存储大量日期(可能足够大以至于使用的堆空间量是一个问题,所以请不要讲过早优化),我想知道使用某种类型的日期是否有意义原始表示而不是 java.util.Date (或其他一些现有的 Date 类)。我知道我可以做一些分析来尝试一下,但是有没有人直接知道单个 Date 对象使用了多少字节的内存?

【问题讨论】:

  • 能否将日期存储为长原语并在需要时将其转换为日期?

标签: java memory date


【解决方案1】:

我的直觉是 Date 的内存开销非常小。检查源代码似乎该类仅包含一个实例字段(长称为毫秒)。这意味着日期对象的大小是 long 的大小加上 Object 实例的大小——也就是说,非常小。

然后我发现this code 创建了数千个对象以确定对象的大小。它说java.util.Date 的大小是 32 字节。将其与仅将日期存储为 long(这是它在内部执行的操作)进行比较 - long 是 8 个字节,因此您必须支付四倍才能获得日期对象。

但是,创建对象的开销并不是很高。因此,如果您真的很担心空间,那么将日期存储为 long 并在需要时创建一个 Date 对象。

【讨论】:

  • 谢谢!我知道对象比原始对象更臃肿,但我没想到会有 4 倍的差异。
  • 这是因为 Date 只是一个长期的包装对象。我快速浏览了 API,所有使 Date 对象有用的东西都已弃用,并已被 Calendar 取代。
  • @Dunes,Calendar 的缺点是它要贵得多。我建议您只在需要时使用日历。
  • 膨胀是一个相对术语。 Java 支持对象的垃圾回收,这至少意味着对象必须存储它的 id 以及该 id 在内存中的当前空间。该对象还需要对其类型的引用。目前可能比我考虑的要多,但是如果您不希望 features 对象提供,这样的存储只会膨胀。如果您不想要这些功能,请分配一个 long 数组并完成它。
  • @Peter 确实,只有拥有大量此类对象才真正重要,但我非常明确地说我确实拥有大量此类对象。在我的应用程序中,我们已经遇到过许多情况,其中开发人员使用了您所描述的“内存很便宜”的理念,只是让它回来咬我们。此外,客户可能希望在无需购买新计算机的情况下使用我们的软件(并且他们可能拥有限制其潜在堆大小的 32 位操作系统)。
【解决方案2】:

使用原语 long ?

它不是一个对象,所以空间更小,日期可以表示为一个长值。当你想存储日期并使用更少的内存时,然后在 Date 和 long 之间来回转换。

【讨论】:

  • 使用原始 long 是我想到的替代方案。但是,我设想编写一堆自定义方法来完成 Date 已经完成的工作,而不是按照您的建议根据需要创建 Date 对象。
  • 确保使用“long”而不是“Long”,否则您将无法获得所需的好处。 long 比 Date 小大约 4 倍。
【解决方案3】:

使用 java 的 instrumentation 框架,getObjectSize 说它是 24B。

【讨论】:

    【解决方案4】:

    here也回答:

    回答这个问题最简单的方法就是看java.util.Date的源码。

    它只有 2 个非静态字段(Java 1.7.0_55):

    private transient long fastTime;
    private transient BaseCalendar.Date cdate;
    

    long 的内存大小为 8 个字节,cdate 是一个大小为 4 个字节的对象引用。所以总共 12 个字节

    如果 cdate 将被实例化,它可能需要内存中的额外字节,但如果你也查看构造函数,有时它甚至不会被触及,而在其他情况下它将是 null-ed构造函数的结尾,所以最终结果也是12字节

    这仅用于创建Date。如果您调用Date 上的方法(例如Date.toString()),创建一个对象并将其存储到cdate 字段中,该字段不会被清除。所以如果你在Date上调用某些方法,它的内存使用会增加。

    注意:对象引用在 64 位 JVM 上可能是 64 位长,在这种情况下,内存使用量为 16 字节。

    注意事项 #2: 另请注意,这只是 Date 对象本身的内存使用情况。您很可能会将其引用存储在某处,例如在数组、列表或其他类中的字段中,这将需要额外的 4 个字节(或者在 64 位 JVM 上可能需要 8 个字节)。

    【讨论】:

      【解决方案5】:

      如果它是字面意义上的日期,而不是日期和时间戳,您甚至可以使用 int:

      20110113

      【讨论】:

        【解决方案6】:

        我尝试根据这里的规则手动计算:http://www.javamex.com/tutorials/memory/object_memory_usage.shtml 并检查 Java 7 中 Date 对象的源代码的内存使用情况。

        Object overhead: 8 bytes => 8 bytes
        + 1 long fastTime: 8 bytes => 16 bytes
        + 1 reference cdate: 4 bytes => 20 bytes
        Rounded up to nearest multiple of 8 => 24 bytes
        

        也许我在计算中遗漏了一些东西,或者在其他答案中使用的工具给出了 32 的结果,包括在计算中对日期本身的引用?

        【讨论】:

          【解决方案7】:

          java.util.Date对象可以用long值表示,long值是8个字节-2^63到(2^63)-1

          【讨论】:

          • 我知道 long 是 8 个字节,并且 can 可以用来表示日期,但我不知道 java.util.Date 是否这样做。此外,一个对象不是原始的这一事实可能意味着它更大,即使由 long 支持。
          • @Micheal,你说得对,日期对象可能大于 8 个字节,但这并不是因为它使用不同的方式来表示内部的日期,而是因为它内部定义了其他几个对象.请参阅 Date 类的实现。 long 足够大以确保保持准确的时间,而不是以毫秒为单位,以纳秒为单位保持时间甚至是很大的。
          猜你喜欢
          • 2010-09-30
          • 1970-01-01
          • 2017-08-12
          • 2010-09-08
          • 1970-01-01
          • 1970-01-01
          • 2011-04-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多