Java虚拟机也可以使用int
- short
字段的宽度(这取决于它们的内部实现)。只有数组(short[]
)是例外,它总是保证它们在内部占用的空间也比int[]
少。 Dalvik 怎么样?
E.g。我有一个包含50个short
类型字段的类。有时在我的应用程序中,存在10000个这样的类。这意味着short
字段应该使用1MB内存,但如果 Dalvik在内部使用4个字节用于short
值,那么这将是2MB内存使用。
我应该期待Dalvik使用多少内存? (这是指内部存储器的使用,我知道它可能不会被系统内存使用所反映,例如因为Dalvik已经从系统中预留了更多的内存。)
答案 0 :(得分:4)
在dalvik中,double和long字段是8个字节,其他所有字符(包括short)都是4个字节。
另一方面,短数组每个元素需要2个字节(除了数组+对象簿记的前端空间)。
<强>阵列强>
new-array
操作码调用dvmAllocArrayByClass
(第71行)来分配空间。然后调用dvmAllocPrimitiveArray
(第113行)。在dvmAllocPrimitiveArray
中的切换中,'S'情况用于短数组。你可以看到它调用allocArray
(第38行),宽度= 2。
在allocArray
内,它执行以下计算来计算数组的大小:
size_t elementShift = sizeof(size_t) * CHAR_BIT - 1 - CLZ(elemWidth);
size_t elementSize = length << elementShift;
size_t headerSize = OFFSETOF_MEMBER(ArrayObject, contents);
size_t totalSize = elementSize + headerSize;
简而言之,在32位系统上,这个计算将是:
size_t elementShift = (4 * 8) - 1 - 30; //== 1;
size_t elementSize = length << 1; //i.e. length * 2
size_t headerSize = <some constant value>;
size_t totalSize = length*2 + <some constant value>;
短数组每个元素需要2个字节。
<强>字段强>
new-instance
操作码调用dvmAllocObject
(第181行)为新对象分配空间。分配的大小基于objectSize
的{{1}}字段。 ClassObject
设置objectSize
(第3543行)。如果在此函数中发现fieldOffset的每个实例都递增,您会注意到它总是以4个字节为单位递增。
短字段需要4个字节。
答案 1 :(得分:2)
(将是一个评论,但它太长了。)
将4字节字段用于“短”本地变量是相当常规的,因为JVM在概念上是一个具有4字节寄存器的机器,并且堆栈帧中的所有其他垃圾都没有多少区别。
例如,字段可能取决于节省存储的权衡与必须在扩展和对齐上花费周期的权衡 - 扩展通常需要一个小周期,甚至在边界对齐方面被认为是“不可知”的体系结构上也是如此。通常是对边界外访问的惩罚,因此“打包”字段而不先重新排列它们以保持字/双字边界可能会降低成本。
因此,如果JVM选择“打包”字段,则通常需要重新排列。朴素的JVM将避免重新排列,因为这使得JVM的几个方面更简单,但是(作为一个示例)我们发现,积极地重新排序和打包实例字段,对于需要大量存储的应用程序,性能提高了30%。
我从来没有看过达尔维克的内脏。标准的Sun派生的JVM历史上(没有看过最近的任何东西)依赖于.class文件中的事物的布局/顺序,因此不“自然地”适合重新排序。但Dalvik重新构成.class文件,因此更适合进行实例字段重新排序。
请注意,为了测试Dalvik包含short
字段的假设,您必须背对背地创建一个包含几十个实例字段的类,然后确定生成的对象大小。另外(假设在第一种情况下看到打包),创建一个交错的short
和int
(或可能long
)字段的类,以查看Dalvik是否重新排序以实现打包。