我非常熟悉HotSpot中堆上对象的布局,但对于Android来说并不是那么多.
例如,在32位HotSpot JVM中,堆上的对象实现为8字节头,后跟对象的字段(一个字节用于boolean引用,四个字节用于引用,其他所有内容按预期方式),布局以某种特定的顺序(对超类中的字段有一些特殊规则),并填充为8个字节的倍数.
我做了一些研究,但我找不到任何特定于Android的信息.
(我有兴趣优化一些极其广泛使用的数据结构,以最大限度地减少Android上的内存消耗.)
nne*_*neo 19
dalvik/vm/oo/Object.h是你的朋友.评论struct Object说:
Run Code Online (Sandbox Code Playgroud)/* * There are three types of objects: * Class objects - an instance of java.lang.Class * Array objects - an object created with a "new array" instruction * Data objects - an object that is neither of the above * * We also define String objects. At present they're equivalent to * DataObject, but that may change. (Either way, they make some of the * code more obvious.) * * All objects have an Object header followed by type-specific data. */
java.lang.Class对象很特别; 它们的布局由ClassObject结构中的Object.h.数组对象很简单:
struct ArrayObject : Object {
/* number of elements; immutable after init */
u4 length;
/*
* Array contents; actual size is (length * sizeof(type)). This is
* declared as u8 so that the compiler inserts any necessary padding
* (e.g. for EABI); the actual allocation may be smaller than 8 bytes.
*/
u8 contents[1];
};
Run Code Online (Sandbox Code Playgroud)
对于数组,宽度为vm/oo/Array.cpp.布尔值是宽度1,对象具有sizeof(Object*)长度(通常为4),并且所有其他基本类型具有其预期(打包)长度.
数据对象非常简单:
/*
* Data objects have an Object header followed by their instance data.
*/
struct DataObject : Object {
/* variable #of u4 slots; u8 uses 2 slots */
u4 instanceData[1];
};
Run Code Online (Sandbox Code Playgroud)
DataObject(所有非类类实例)的布局由computeFieldOffsetsin控制vm/oo/Class.cpp.根据评论:
/*
* Assign instance fields to u4 slots.
*
* The top portion of the instance field area is occupied by the superclass
* fields, the bottom by the fields for this class.
*
* "long" and "double" fields occupy two adjacent slots. On some
* architectures, 64-bit quantities must be 64-bit aligned, so we need to
* arrange fields (or introduce padding) to ensure this. We assume the
* fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
* we can just ensure that the offset is "even". To avoid wasting space,
* we want to move non-reference 32-bit fields into gaps rather than
* creating pad words.
*
* In the worst case we will waste 4 bytes, but because objects are
* allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
* (assuming this is the most-derived class).
*
* Pad words are not represented in the field table, so the field table
* itself does not change size.
*
* The number of field slots determines the size of the object, so we
* set that here too.
*
* This function feels a little more complicated than I'd like, but it
* has the property of moving the smallest possible set of fields, which
* should reduce the time required to load a class.
*
* NOTE: reference fields *must* come first, or precacheReferenceOffsets()
* will break.
*/
Run Code Online (Sandbox Code Playgroud)
因此,超类字段首先(像往常一样),然后是引用类型字段,后跟一个32位字段(如果可用,如果需要填充,因为有奇数个32位引用字段),后跟64比特字段.接下来是常规的32位字段.请注意,所有字段都是32位或64位(填充较短的基元).特别是,此时,VM不会使用少于4个字节存储字节/字符/短/布尔字段,但它理论上肯定可以支持这一点.
请注意,所有这些都是基于提交时读取Dalvik源代码43241340(2013年2月6日).由于VM的这个方面似乎没有公开记录,因此您不应该依赖它来对VM的对象布局进行稳定的描述:它可能会随着时间的推移而发生变化.