Java对象数组空元素内存
Java Object Array null Element Memory
目前我正在使用以下数据结构:
MyObject[] arr = new MyObject[100]
现在数组中的大部分字段实际上都是空的(假设 97%)
据我所知,JVM 为每个字段保留了 MyObject
的一个实例所需的内存,因此即使从未真正使用过,也会保留大量内存。
有没有办法节省内存?就像按需只为 MyObject
分配 space 一样?
有比简单数组更好的数据结构吗? (需要既高效又快速)
As far as I can see the JVM reserves for each field the requiered memory for one instance of MyObject so a lot of memory is reserved even though it is never really used.
不,不是。它为 100 个 对象引用 保留了足够的内存,而不是 MyObject
的 100 个实例。对象引用不大(32 位或 64 位,详见 this answer)。下面是 ASCII 艺术。
现在,如果您对保留 int
或 long
大小的 100 个插槽感到困扰,您可以使用 ArrayList
,它将重新分配一个支持数组作为必要的(但这会增加内存碎片),一个 LinkedList
根本不使用数组(但它 确实 具有的条目具有更高的内存开销) ,甚至是 Map
之类的结构,它根本(不一定)使用数组(但每个条目的开销同样更高)。
100 位数组的 ASCII 艺术和详细信息:
因此,当您首次创建该数组时,内存中的内容如下:
+-----------+
| arr |
+-----------+ +------------+
| reference |------>| MyObject[] |
+-----------+ +------------+
| null |
| null |
| null |
| (96 more) |
| null |
+------------+
然后你分配一个实例,比如:
arr[1] = new MyObject();
这给了你
+-----------+
| arr |
+-----------+ +------------+
| reference |------>| MyObject[] |
+-----------+ +------------+
| null | +-------------------+
| reference |---->| MyObject instance |
| null | +-------------------+
| (96 more) | | someField |
| null | | someOtherField |
+------------+ | ... |
+-------------------+
...那么也许你再添加一个:
+-----------+
| arr |
+-----------+ +------------+
| reference |------>| MyObject[] |
+-----------+ +------------+
| null | +-------------------+
| reference |---->| MyObject instance |
| reference |--+ +-------------------+
| (96 more) | | | someField |
| null | | | someOtherField |
+------------+ | | ... |
| +-------------------+
|
| +-------------------+
+->| MyObject instance |
+-------------------+
| someField |
| someOtherField |
| ... |
+-------------------+
...当您在数组中存储更多实例时依此类推。
目前我正在使用以下数据结构:
MyObject[] arr = new MyObject[100]
现在数组中的大部分字段实际上都是空的(假设 97%)
据我所知,JVM 为每个字段保留了 MyObject
的一个实例所需的内存,因此即使从未真正使用过,也会保留大量内存。
有没有办法节省内存?就像按需只为 MyObject
分配 space 一样?
有比简单数组更好的数据结构吗? (需要既高效又快速)
As far as I can see the JVM reserves for each field the requiered memory for one instance of MyObject so a lot of memory is reserved even though it is never really used.
不,不是。它为 100 个 对象引用 保留了足够的内存,而不是 MyObject
的 100 个实例。对象引用不大(32 位或 64 位,详见 this answer)。下面是 ASCII 艺术。
现在,如果您对保留 int
或 long
大小的 100 个插槽感到困扰,您可以使用 ArrayList
,它将重新分配一个支持数组作为必要的(但这会增加内存碎片),一个 LinkedList
根本不使用数组(但它 确实 具有的条目具有更高的内存开销) ,甚至是 Map
之类的结构,它根本(不一定)使用数组(但每个条目的开销同样更高)。
100 位数组的 ASCII 艺术和详细信息:
因此,当您首次创建该数组时,内存中的内容如下:
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | | null | | null | | (96 more) | | null | +------------+
然后你分配一个实例,比如:
arr[1] = new MyObject();
这给了你
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | +-------------------+ | reference |---->| MyObject instance | | null | +-------------------+ | (96 more) | | someField | | null | | someOtherField | +------------+ | ... | +-------------------+
...那么也许你再添加一个:
+-----------+ | arr | +-----------+ +------------+ | reference |------>| MyObject[] | +-----------+ +------------+ | null | +-------------------+ | reference |---->| MyObject instance | | reference |--+ +-------------------+ | (96 more) | | | someField | | null | | | someOtherField | +------------+ | | ... | | +-------------------+ | | +-------------------+ +->| MyObject instance | +-------------------+ | someField | | someOtherField | | ... | +-------------------+
...当您在数组中存储更多实例时依此类推。