对象引用有多大?

2022-09-02 01:08:22

Android 的 Java VM 中的引用占用的大小是多少?

更多信息:

我的意思是,如果我们有

String str = "Watever";

我需要什么,而不是。-- 是保存在指针(或引用)所指向的位置中的内容。str"Watever""Watever"str

另外,如果我们有

String str = null;

它消耗多少内存?它和另一个一样吗?str

现在,如果我们有:

Object obj[] = new object[2];

消耗多少,消耗多少?objobj[1]obj[2]


这个问题的原因如下:(以防有人可以推荐一些东西)。

我正在开发一个应用程序,该应用程序可以管理从互联网上下载的许多图片。我开始将这些图片存储在“银行”上(由图片列表组成)。

在图库上显示这些图片时,我曾经在列表中搜索图片(SLOW),然后,如果图片不存在,我曾经显示临时下载图像,直到下载图片为止。

由于这种情况发生在UI Thread上,因此应用程序变得非常慢,因此我想在银行上实现哈希表,而不是我拥有的列表。

正如我之前解释的那样,此搜索发生在UI线程中(我无法更改它)。因此,如果冲突开始减慢线程速度,则它们可能会成为一个问题。

我读过“为了平衡时间和空间效率,哈希表应该大约半满”,但这会使冲突在一半的时间内发生(对于UI线程不实用)。这让我想到有一个非常长的哈希表(与保存的图片数量相比)并使用更多的RAM(具有更少的可用VMHeap)。

在确定哈希表的大小之前,我想知道它将消耗多少内存才能不夸大其词。

我知道与图片可能消耗的内存相比,哈希表的大小可能非常小,但我想确保我消耗的内存不会超过必要的内存。


在问这个问题之前,我搜索了其他地方,在

Java中的对象引用有多大,它究竟包含哪些信息?

java 中的引用类型大小

哈希教程

(是的,我知道其中两个地方相互矛盾,这是问题的部分原因)。


答案 1

对象或数组引用在 32 位 JVM 或 Davlik VM 上占用一个 32 位字(4 字节)。A 与引用占用相同的空间。(它必须这样做,因为空值必须适合引用类型的插槽;即实例字段,局部变量等。null

另一方面,一个对象至少占用 2 个 32 位字(8 个字节),一个数组至少占用 3 个 32 位字(12 个字节)。实际大小取决于对象的字段数和种类,以及数组的元素数和种类。


对于 64 位 JVM,引用的大小为 64 位,除非您已将 JVM 配置为使用压缩指针:

-XX:+UseCompressedOops 允许使用压缩指针(对象引用表示为 32 位偏移量而不是 64 位指针),以便在 Java 堆大小小于 32gb 的情况下优化 64 位性能。


我想,这就是你问题的症结所在。

在确定哈希表的大小之前,我想知道它将消耗多少内存才能不夸大其词。

如果分配具有较大初始大小的 或,则大部分空间将被哈希数组占用。这是一个引用数组,因此大小将为 32 位字。这不太可能是重要的...除非你得到你的尺寸估计严重错误。HashMapHashtable3 + initialSize

但是,我认为您可能不必要地担心性能。如果将对象存储在默认分配的 或 中,则该类将在哈希表变大时自动调整其大小。因此,如果您的对象具有不错的哈希函数(不要太慢,不会将所有内容哈希化为少量值),则哈希表不应该是直接的CPU性能问题。HashMapHashtable


答案 2

参考文献几乎是免费的。与图像相比更是如此。

在地图中发生一些碰撞并不是一个真正的问题。冲突的解决速度远远快于通过项目列表进行线性搜索。也就是说,通过排序的项目列表进行二进制搜索将是降低内存使用率的好方法(与Map相比)。

我可以保证地图初始尺寸较小的有效性 - 我最近写了一个程序,使Trie结构为170000个英语单词。当我将初始大小设置为 26 时,当我得到以 R 开头的单词时,我的内存就会耗尽。将其减少到 5,我能够创建没有内存问题的映射,并且可以立即有效地搜索树(有许多冲突)。

[编辑]如果引用为 32 位(4 字节),而平均图像约为 2 MB,则可以将 500000 个引用放入与单个图像相同的空间中。您不必担心引用。