Подтвердить что ты не робот

Как объекты Java размещаются в памяти на Android?

Я довольно хорошо знаком с компоновкой объектов в куче в HotSpot, но не для Android.

Например, в 32-битной JVM HotSpot объект в куче реализуется как 8-байтовый заголовок, за которым следуют поля объекта (один байт для boolean, четыре байта для ссылки и все остальное как и ожидалось), изложенные в определенном порядке (с некоторыми специальными правилами для полей из суперклассов) и дополненные кратным 8 байтам.

Я провел некоторое исследование, но я не могу найти какую-либо информацию для Android.

(меня интересует оптимизация некоторых чрезвычайно широко используемых структур данных для минимизации потребления памяти на Android.)

4b9b3361

Ответ 1

dalvik/vm/oo/Object.h - ваш друг здесь. В комментарии для struct Object говорится:

/*
 * 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];
};

Для массивов ширины находятся в 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];
};

Макет DataObject (все экземпляры класса не класса) определяется computeFieldOffsets в 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.
 */

Итак, сначала появляются поля суперкласса (как обычно), за которыми следуют поля ссылочного типа, за которым следует одно 32-битовое поле (если доступно, и если требуется заполнить, потому что имеется нечетное число 32-битных полей ссылок) за которым следуют 64-битные поля. Последовали обычные 32-битные поля. Обратите внимание, что все поля 32-разрядные или 64-разрядные (более короткие примитивы дополняются). В частности, на данный момент VM не хранит байты/ char/короткие/логические поля с использованием менее 4 байтов, хотя это, безусловно, может поддержать это теоретически.

Обратите внимание, что все это основано на чтении исходного кода Dalvik с фиксацией 43241340 (6 февраля 2013 г.). Поскольку этот аспект виртуальной машины не является публично документированным, вы не должны полагаться на это, чтобы быть стабильным описанием макета объекта VM: он может меняться со временем.