【发布时间】:2011-01-13 15:46:33
【问题描述】:
我需要存储大量日期(可能足够大以至于使用的堆空间量是一个问题,所以请不要讲过早优化),我想知道使用某种类型的日期是否有意义原始表示而不是 java.util.Date (或其他一些现有的 Date 类)。我知道我可以做一些分析来尝试一下,但是有没有人直接知道单个 Date 对象使用了多少字节的内存?
【问题讨论】:
-
能否将日期存储为长原语并在需要时将其转换为日期?
我需要存储大量日期(可能足够大以至于使用的堆空间量是一个问题,所以请不要讲过早优化),我想知道使用某种类型的日期是否有意义原始表示而不是 java.util.Date (或其他一些现有的 Date 类)。我知道我可以做一些分析来尝试一下,但是有没有人直接知道单个 Date 对象使用了多少字节的内存?
【问题讨论】:
我的直觉是 Date 的内存开销非常小。检查源代码似乎该类仅包含一个实例字段(长称为毫秒)。这意味着日期对象的大小是 long 的大小加上 Object 实例的大小——也就是说,非常小。
然后我发现this code 创建了数千个对象以确定对象的大小。它说java.util.Date 的大小是 32 字节。将其与仅将日期存储为 long(这是它在内部执行的操作)进行比较 - long 是 8 个字节,因此您必须支付四倍才能获得日期对象。
但是,创建对象的开销并不是很高。因此,如果您真的很担心空间,那么将日期存储为 long 并在需要时创建一个 Date 对象。
【讨论】:
使用原语 long ?
它不是一个对象,所以空间更小,日期可以表示为一个长值。当你想存储日期并使用更少的内存时,然后在 Date 和 long 之间来回转换。
【讨论】:
使用 java 的 instrumentation 框架,getObjectSize 说它是 24B。
【讨论】:
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 个字节)。
【讨论】:
如果它是字面意义上的日期,而不是日期和时间戳,您甚至可以使用 int:
20110113
【讨论】:
我尝试根据这里的规则手动计算: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 的结果,包括在计算中对日期本身的引用?
【讨论】:
java.util.Date对象可以用long值表示,long值是8个字节-2^63到(2^63)-1
【讨论】: