2013-02-06 15 views
20

Sono abbastanza familiare con il layout degli oggetti sullo heap in HotSpot, ma non così tanto per Android.In che modo gli oggetti Java sono disposti in memoria su Android?

Ad esempio, in una JVM HotSpot a 32 bit, un oggetto sull'heap viene implementato come un'intestazione da 8 byte, seguito dai campi dell'oggetto (un byte per boolean, quattro byte per un riferimento e tutto il resto previsto), disposto in un ordine specifico (con alcune regole speciali per i campi delle superclassi) e inserito in un multiplo di 8 byte.

Ho fatto qualche ricerca, ma non riesco a trovare alcuna informazione specifica per Android.

(Mi interessa ottimizzare alcune strutture di dati estremamente ampiamente utilizzati per ridurre al minimo il consumo di memoria su Android.)

+0

Hai letto/visto questo: https://sites.google.com/site/io/dalvik-vm-internals/ –

+0

Non l'avevo, ma non ho le informazioni che desidero. Parla del layout dell'APK e del bytecode, ma non degli oggetti sull'heap. –

+0

Dalvik sembra quasi identico: 4 byte di classe ptr, 4 byte di blocco, quindi dati: https://android.googlesource.com/platform/dalvik/+/master/vm/oo/Object.h – Chris

risposta

17

dalvik/vm/oo/Object.h è tuo amico qui. Il commento per struct Object dice:

/* 
* 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 oggetti sono speciali; il loro layout è definito dalla struttura ClassObject in Object.h. oggetti array sono semplici:

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

Per gli array, le larghezze sono in vm/oo/Array.cpp. I booleani sono larghezza 1, gli oggetti hanno lunghezza sizeof(Object*) (in genere 4) e tutti gli altri tipi primitivi hanno la lunghezza prevista (imballata).

oggetti dati sono molto semplici:

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

il layout di una (tutte le istanze di classe non-Class) DataObject è disciplinato dalle computeFieldOffsets in vm/oo/Class.cpp. Secondo il commento c'è:

/* 
* 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. 
*/ 

Quindi, i campi della superclasse arrivato, primo (come al solito), seguita da campi di riferimento di tipo, seguito da un singolo campo a 32 bit (se disponibile, e se è necessario padding perché c'è un numero dispari di campi di riferimento a 32 bit) seguito da campi a 64 bit. Seguono i normali campi a 32 bit. Si noti che tutti i campi sono a 32 o 64 bit (le primitive più corte sono riempite). In particolare, in questo momento, la VM non memorizza i campi byte/char/short/boolean con meno di 4 byte, anche se in teoria potrebbe supportarli.

Si noti che tutto ciò si basa sulla lettura del codice sorgente Dalvik a partire dal commit 43241340 (6 febbraio 2013). Dal momento che questo aspetto della VM non sembra essere pubblicamente documentato, non si deve fare affidamento su ciò per essere una descrizione stabile del layout dell'oggetto della VM: potrebbe cambiare nel tempo.

Problemi correlati