java.util.Date对象使用多少字节的内存?

java.util.Date对象使用多少字节的内存?,java,memory,date,Java,Memory,Date,我需要存储大量的日期(可能足够大,使用的堆空间量是一个问题,所以请不要讲过早的优化),我想知道使用某种原语表示而不是java.util.Date(或其他现有的日期类)是否有意义。我知道我可以做一些分析来尝试一下,但是有人知道一个日期对象使用多少字节的内存吗?使用long原语 它不是一个对象,因此空间较小,日期可以表示为长值。然后在日期和长时间之间来回转换,以便存储日期并使用更少的内存。如果它是字面上的日期,而不是日期和时间戳,您甚至可以使用int: 20110113

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

使用long原语


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

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


20110113

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

然后我发现它创建了数千个对象来确定对象的大小。它说
java.util.Date
的大小是32字节。与仅将日期存储为long(这是它内部的功能)相比,long是8个字节,因此您必须支付四倍的费用才能方便地拥有一个date对象


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

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

我尝试了一个基于这里规则的手动计算:并检查Java 7中日期对象的源代码和内存使用情况

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个结果,在计算中包括了对日期本身的引用

答案也一样:

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

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

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

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

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

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


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

您是否可以将日期存储为long原语,并在需要时将其转换为日期?我想到的替代方法是使用long原语。但是,我设想编写一系列自定义方法来完成Date已经完成的工作,而不是按照您的建议创建所需的日期对象。请确保使用“long”而不是“long”,否则您将无法获得所需的好处。long大约比日期小4倍。我知道long是8字节,可以用来表示日期,但我不知道java.util.Date是否就是这样做的。此外,对象不是基元这一事实可能意味着它更大,即使后面有一个长的。@Micheal,你是对的,date对象可能大于8字节,但这不是因为它使用不同的方式来表示内部的日期,而是因为它内部定义了几个其他对象。请参见Date类的实现。long足够大,可以确保保存精确的时间,而不是jsut(毫秒),它甚至可以保存纳秒的时间。谢谢!我知道对象比原语更臃肿,但我没想到会有4倍的差异,因为Date只是一个包装器对象。我快速浏览了一下API,所有使Date对象有用的东西都被弃用了,并被Calendar所取代。@Dunes,Calendar的缺点是它要贵得多。我建议你们只使用你们需要的日历。膨胀是一个相对的术语。Java支持对象的垃圾收集,这至少意味着对象必须存储其id以及该id在内存中的当前空间。该对象还需要对其类型的引用。这可能比我目前考虑的要多,但只有当您不希望对象提供的特性时,这样的存储才会膨胀。如果您不想要这些功能,请分配一个长数组并完成它。@Peter确实,只有当您有很多这样的对象时,它才真正重要,但我非常明确地说,我确实有很多这样的对象。在我的应用程序中,我们已经遇到过很多这样的例子:一个开发人员使用了您描述的“内存很便宜”的理念,结果却被它咬了一口。此外,客户可能希望使用我们的软件而不需要购买新的计算机(而且他们可能有一个32位操作系统,限制了潜在的堆大小)。
private transient long fastTime;
private transient BaseCalendar.Date cdate;