【问题标题】:How big is an object reference?对象引用有多大?
【发布时间】:2011-04-30 04:10:50
【问题描述】:

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

更多信息:

我的意思是,如果我们有

String str = "Watever";

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

如果我们有

String str = null;

它消耗多少内存?和其他str一样吗?

现在,如果我们有:

Object obj[] = new object[2];

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


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

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

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

由于发生在 UI Thread 上,应用程序变得非常慢,所以我想在银行上实现一个哈希表,而不是我的列表。

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

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

在确定哈希表的大小之前,我想知道它会消耗多少内存,以免被夸大。

我知道哈希表的大小与图片可能消耗的内存相比可能非常小,但我想确保我没有消耗过多的内存。


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

How big is an object reference in Java and precisely what information does it contain?

reference type size in java

Hashing Tutorial

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

【问题讨论】:

    标签: java android pointers reference size


    【解决方案1】:

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

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


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

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


    我想这是你问题的关键。

    在确定哈希表的大小之前,我想知道它会消耗多少内存,以免被夸大。

    如果分配初始大小较大的HashMapHashtable,则大部分空间将被散列数组占用。这是一个引用数组,因此大小将为3 + initialSize 32 位字。这不太可能很重要……除非您对尺寸的估计严重错误。

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

    【讨论】:

    • 谢谢。这解决了我的问题。但只是为了更好地理解这一点。您能否在数组中多解释一下。如果我有一个数组,比如说 Object[2],每个对象将占用 3 个单词 + 2 个单词(3 + 2 * 2 = 7 个单词)??
    • 没有。数组标题需要 3 个单词 + 每个元素需要 1 个单词;即5个字。 (该数组包含对 Objects 而非实际 Objects 的引用。)
    • 谢谢你或第二部分和评论,我以前从未使用过哈希表,所以第二部分真的很有帮助。
    • 泛型对象呢?他们也用三个词吗?
    • 好的,我认为通用对象也只使用了 2 个单词,因为类型擦除。
    【解决方案2】:

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

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

    我可以保证 Maps 具有较小的初始大小的有效性 - 我最近编写了一个程序,该程序可以生成 170000 个英语单词的 Trie 结构。当我将初始大小设置为 26 时,当我找到以 R 开头的单词时,我的内存就会用完。将它减少到 5,我能够创建没有内存问题的地图,并且可以搜索树(有很多碰撞)在短时间内有效。

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

    【讨论】:

    • 非常感谢。我给斯蒂芬 C 的答案是因为他回答了确切的问题,但我给你一个 +1 是因为你证实了我的想法并在哈希表上给了我一个很好的例子(我从未创建过) .我认为这个问题对我同样有帮助。
    • 另外,我的平均图像大小是 60k,因此可以容纳大约 7500 个 32 位引用。它绰绰有余。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多