class内存布局可以从下面这个函数来分析一个Java类对应的内存布局:
inline uint32_t Class::ComputeClassSize(bool has_embedded_tables, uint32_t num_vtable_entries, uint32_t num_8bit_static_fields, uint32_t num_16bit_static_fields, uint32_t num_32bit_static_fields, uint32_t num_64bit_static_fields, uint32_t num_ref_static_fields, size_t pointer_size) { // Space used by java.lang.Class and its instance fields. uint32_t size = sizeof(Class); // art::mirror::Class 这个C++ 类的size,在7.0,64bit上,为128 // Space used by embedded tables. if (has_embedded_tables) { const uint32_t embedded_imt_size = kImtSize * ImTableEntrySize(pointer_size); // Interface method table占用的大小,table size是64,固定的,大小为 64* pointer_size(32bit:4, 64bit:8) const uint32_t embedded_vtable_size = num_vtable_entries * VTableEntrySize(pointer_size); // vtable 占用的大小,里面填充的是 Java类对应的 virtual method size = RoundUp(size + sizeof(uint32_t) /* embedded vtable len */, pointer_size) + // 在 art::mirror::Class 数据之后,紧接着有一个 4byte 记录 vtable的size,这里需要根据 pointer_size 进行align embedded_imt_size + embedded_vtable_size; // 再加上 interface table 的size 和 vtable 的size } // Space used by reference statics. size += num_ref_static_fields * sizeof(HeapReference
只有通过 invoke-virtual 调用的方法才是 virtual method;
class.h 中 art::mirror::Class类的TODO中有说明一个Class的内存布局,在art::mirror::Class 的数据只有还有:
// TODO: ? // initiating class loader list // NOTE: for classes with low serialNumber, these are unused, and the // values are kept in a table in gDvm. // InitiatingLoaderList initiating_loader_list_; // The following data exist in real class objects. // 在一个正式的 java 类的内存空间中,下面这些数据会紧挨在 sizeof(art::mirror::Class)+ 4 的尾部; // Embedded Imtable, for class object that's not an interface, fixed size. // ImTableEntry embedded_imtable_[0]; // Interface method table,大小固定为 64个元素; // Embedded Vtable, for class object that's not an interface, variable size. // VTableEntry embedded_vtable_[0]; // Virtual method table,大小可变,由紧挨 sizeof(art::mirror::Class) 尾部的 4 个字节来记录; // Static fields, variable size. // uint32_t fields_[0];
内存布局:
total
|
起始地址
|
内容
|
size(byte)
|
---|---|---|---|
mem_start | art::mirror::Class | sizeof(art::mirror::Class) | |
mem_start+sizeof(art::mirror::Class) | vtable_len |
4 | |
mem_start+sizeof(art::mirror::Class)+ 4 | padding | padding_size(当padding不存在时,这个值为0) | |
mem_start+sizeof(art::mirror::Class)+ 4 + padding_size | Interface method table | 64* pointer_size | |
mem_start+sizeof(art::mirror::Class)+ 4+ padding_size+64* pointer_size | Virtual mehtod table | vtable_len* pointer_size | |
mem_start+sizeof(art::mirror::Class)+ 4+ padding_size+64* pointer_size + vtable_len* pointer_size | static fields | 大小可变,由 java class 的 static 成员的类型和个数决定 | |
total(class size) | mem_start+sizeof(art::mirror::Class)+ 4+ padding_size+64* pointer_size + vtable_len* pointer_size+ sizeof(static fields) |
举例:
选用一个class:
这个class的指针是 0x12eb4000, 可以看到其对应java 类: TelephonyComponentFactory
(gdb) art_printn_class 0x12eb4000
com.android.internal.telephony.TelephonyComponentFactory
查看其内存:
(gdb) x /300wx 0x12eb4000
0x12eb4000: {0x707f1d88 0x00000000 0x00000000 0x00000000
0x12eb4010: 0x00000000 0x715990c8 0x00000000 0x00000000
0x12eb4020: 0x707f27f0 0x00000000 0x00000000 0x00080001
0x12eb4030: 0x715afb08 0x00000000 0x00000000 0x00000000
0x12eb4040: 0x965e0890 0x0000007f 0x965e0868 0x0000007f
0x12eb4050: 0x00000001 [0x00000398] 0x00005ede 0x000000f2 // 0x00000398 对应 art::mirror::Class的 class_size_ ,代表这个类的大小是 920 bytes;
0x12eb4060: 0x0000020c 0x00000000 [0x00000002] 0x00000008 // 中括号中 0x2 对应 art::mirror::Class的 num_reference_static_fields_ ,代表这个类有 2 个reference 类型的的 static 成员;
0x12eb4070: 0x00020000 0x00000000 0x0000000a 0x00030019} // 大括号内为 art::mirror::Class 的内容
0x12eb4080: 0x00000021 [0x00000000] [[0x70c2d038 0x00000000 // 0x00000021 为 vtable_len,即这个类中有 33 个 virtual method,这一行中括号内容为 algin pointer_size时填充的4个byte的 0;
0x12eb4090: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40a0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40b0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40c0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40d0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40e0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb40f0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4100: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4110: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4120: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4130: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4140: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4150: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4160: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4170: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4180: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4190: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41a0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41b0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41c0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41d0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41e0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb41f0: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4200: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4210: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4220: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4230: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4240: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4250: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4260: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4270: 0x70c2d038 0x00000000 0x70c2d038 0x00000000
0x12eb4280: 0x70c2d038 0x00000000]] {0x70c03168 0x00000000 // 双中括号中包含的是 Interface method table,共有 64 个 pointer_size的数据;
0x12eb4290: 0x70c031a0 0x00000000 0x70c031d8 0x00000000
0x12eb42a0: 0x70c03210 0x00000000 0x70c03248 0x00000000
0x12eb42b0: 0x70c03280 0x00000000 0x70c032b8 0x00000000
0x12eb42c0: 0x70c032f0 0x00000000 0x70c03328 0x00000000
0x12eb42d0: 0x70c03360 0x00000000 0x70c03398 0x00000000
0x12eb42e0: 0x965e0940 0x0000007f 0x965e0978 0x0000007f
0x12eb42f0: 0x965e09b0 0x0000007f 0x965e09e8 0x0000007f
0x12eb4300: 0x965e0a20 0x0000007f 0x965e0a58 0x0000007f
0x12eb4310: 0x965e0a90 0x0000007f 0x965e0ac8 0x0000007f
0x12eb4320: 0x965e0b00 0x0000007f 0x965e0b38 0x0000007f
0x12eb4330: 0x965e0b70 0x0000007f 0x965e0ba8 0x0000007f
0x12eb4340: 0x965e0be0 0x0000007f 0x965e0c18 0x0000007f
0x12eb4350: 0x965e0c50 0x0000007f 0x965e0c88 0x0000007f
0x12eb4360: 0x965e0cc0 0x0000007f 0x965e0cf8 0x0000007f
0x12eb4370: 0x965e0d30 0x0000007f 0x965e0d68 0x0000007f
0x12eb4380: 0x965e0da0 0x0000007f 0x965e0dd8 0x0000007f} // 大括号中包含的是 virtual method table,共有 33 个 pointer_size 的数据;
0x12eb4390: [0x70aed7b8 0x12d90a20] 0x00000000 0x00000000 // 中括号中包含的是 static 成员变量的地址(对象),或者成员变量的值(基础类型);
这个对象的大小是 920, 可以根据我们的分析计算一下:
(gdb) p 0x12eb4398-0x12eb4000
$20 = 920
大小是吻合的;
其两个static reference field :[0x70aed7b8 0x12d90a20]也可以验证一下:
其两个field分别是 String对象和 TelephonyComponentFactory 对象;
51public class TelephonyComponentFactory {
52 protected static String LOG_TAG = "TelephonyComponentFactory";
53
54 private static TelephonyComponentFactory sInstance;
(gdb) art_print_object 0x70aed7b8
$21 = (art::mirror::Class *) 0x707f22c0
java.lang.String
(gdb) art_print_object 0x12d90a20
$22 = (art::mirror::Class *) 0x12eb4800
Cannot access memory at address 0x10
第二个TelephonyComponentFactory没有打印出来类名,是由于这个环境是发生FC的内存场景,
0x12d90a20这个对象对应的class 0x12eb4800 的内存被破坏了;我从上下文分析的确认 0x12d90a20 确实是 TelephonyComponentFactory;
(gdb) p /x *(art::mirror::Class*)0x12eb4000
$40 = {
= {
static kVTableLength = 0xb,
static hash_code_seed = {
> = {
> = {
> = {
__a_ = 0x1f02f126
}, }, }, },
klass_ = {
> = {
reference_ = 0x707f1d88
}, },
monitor_ = 0x0
},
members of art::mirror::Class:
static kClassWalkSuper = 0xc0000000,
static kImtSize = 0x40,
annotation_type_ = {
> = {
reference_ = 0x0
}, },
class_loader_ = {
> = {
reference_ = 0x0
}, },
component_type_ = {
> = {
reference_ = 0x0
}, },
dex_cache_ = {
> = {
reference_ = 0x715990c8
}, },
iftable_ = {
> = {
reference_ = 0x0
}, },
name_ = {
> = {
reference_ = 0x0
}, },
super_class_ = {
> = {
reference_ = 0x707f27f0
}, },
verify_error_ = {
> = {
reference_ = 0x0
}, },
vtable_ = {
> = {
---Type to continue, or q to quit---
reference_ = 0x0
}, },
access_flags_ = 0x80001,
dex_cache_strings_ = 0x715afb08,
ifields_ = 0x0,
methods_ = 0x7f965e0890,
sfields_ = 0x7f965e0868,
class_flags_ = 0x1,
class_size_ = 0x398,
clinit_thread_id_ = 0x5ede,
dex_class_def_idx_ = 0xf2,
dex_type_idx_ = 0x20c,
num_reference_instance_fields_ = 0x0,
num_reference_static_fields_ = 0x2,
object_size_ = 0x8,
primitive_type_ = 0x20000,
reference_instance_offsets_ = 0x0,
status_ = 0xa,
copied_methods_offset_ = 0x19,
virtual_methods_offset_ = 0x3,
static java_lang_Class_ = {
root_ = {
> = {
reference_ = 0x707f1d88
}, }
}
}
memory layout:
|
module
|
size(byte)
|
---|---|---|
art::mirror::Object | 8 | |
super_class->GetObjectSize() | super class object size | |
reference_instance_fileds | num * 4 + gaps_size | |
Primitive fields | primitive fileds size | |
total | All | klass->object_size_ |
可以通过 bool ClassLinker::LinkFields 函数分析:
bool ClassLinker::LinkFields(Thread* self,
Handle klass,
bool is_static,
size_t* class_size) {
self->AllowThreadSuspension();
const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
LengthPrefixedArray* const fields = is_static ? klass->GetSFieldsPtr() :
klass->GetIFieldsPtr();
// Initialize field_offset
MemberOffset field_offset(0);
if (is_static) {
field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_);
} else {
mirror::Class* super_class = klass->GetSuperClass();
if (super_class != nullptr) {
CHECK(super_class->IsResolved())
<< PrettyClass(klass.Get()) << " " << PrettyClass(super_class);
field_offset = MemberOffset(super_class->GetObjectSize());
}
}
CHECK_EQ(num_fields == 0, fields == nullptr) << PrettyClass(klass.Get());
// we want a relatively stable order so that adding new fields
// minimizes disruption of C++ version such as Class and Method.
//
// The overall sort order order is:
// 1) All object reference fields, sorted alphabetically.
// 2) All java long (64-bit) integer fields, sorted alphabetically.
// 3) All java double (64-bit) floating point fields, sorted alphabetically.
// 4) All java int (32-bit) integer fields, sorted alphabetically.
// 5) All java float (32-bit) floating point fields, sorted alphabetically.
// 6) All java char (16-bit) integer fields, sorted alphabetically.
// 7) All java short (16-bit) integer fields, sorted alphabetically.
// 8) All java boolean (8-bit) integer fields, sorted alphabetically.
// 9) All java byte (8-bit) integer fields, sorted alphabetically.
//
// Once the fields are sorted in this order we will attempt to fill any gaps that might be present
// in the memory layout of the structure. See ShuffleForward for how this is done.
std::deque grouped_and_sorted_fields;
const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension(
"Naked ArtField references in deque");
for (size_t i = 0; i < num_fields; i++) {
grouped_and_sorted_fields.push_back(&fields->At(i));
}
std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(),
LinkFieldsComparator());
// References should be at the front.
size_t current_field = 0;
size_t num_reference_fields = 0;
FieldGaps gaps;
for (; current_field < num_fields; current_field++) {
ArtField* field = grouped_and_sorted_fields.front();
Primitive::Type type = field->GetTypeAsPrimitiveType();
bool isPrimitive = type != Primitive::kPrimNot;
if (isPrimitive) {
break; // past last reference, move on to the next phase
}
if (UNLIKELY(!IsAligned)>(
field_offset.Uint32Value()))) {
MemberOffset old_offset = field_offset;
field_offset = MemberOffset(RoundUp(field_offset.Uint32Value(), 4));
AddFieldGap(old_offset.Uint32Value(), field_offset.Uint32Value(), &gaps);
}
DCHECK_ALIGNED(field_offset.Uint32Value(), sizeof(mirror::HeapReference));
grouped_and_sorted_fields.pop_front();
num_reference_fields++;
field->SetOffset(field_offset);
field_offset = MemberOffset(field_offset.Uint32Value() +
sizeof(mirror::HeapReference));
}
// Gaps are stored as a max heap which means that we must shuffle from largest to smallest
// otherwise we could end up with suboptimal gap fills.
ShuffleForward<8>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps);
ShuffleForward<4>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps);
ShuffleForward<2>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps);
ShuffleForward<1>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps);
CHECK(grouped_and_sorted_fields.empty()) << "Missed " << grouped_and_sorted_fields.size() <<
" fields.";
self->EndAssertNoThreadSuspension(old_no_suspend_cause);
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
if (!is_static && klass->DescriptorEquals("Ljava/lang/ref/Reference;")) {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields) << PrettyClass(klass.Get());
CHECK_STREQ(fields->At(num_fields - 1).GetName(), "referent")
<< PrettyClass(klass.Get());
--num_reference_fields;
}
size_t size = field_offset.Uint32Value();
// Update klass
if (is_static) {
klass->SetNumReferenceStaticFields(num_reference_fields);
*class_size = size;
} else {
klass->SetNumReferenceInstanceFields(num_reference_fields);
mirror::Class* super_class = klass->GetSuperClass();
if (num_reference_fields == 0 || super_class == nullptr) {
// object has one reference field, klass, but we ignore it since we always visit the class.
// super_class is null iff the class is java.lang.Object.
if (super_class == nullptr ||
(super_class->GetClassFlags() & mirror::kClassFlagNoReferenceFields) != 0) {
klass->SetClassFlags(klass->GetClassFlags() | mirror::kClassFlagNoReferenceFields);
}
}
if (kIsDebugBuild) {
DCHECK_EQ(super_class == nullptr, klass->DescriptorEquals("Ljava/lang/Object;"));
size_t total_reference_instance_fields = 0;
mirror::Class* cur_super = klass.Get();
while (cur_super != nullptr) {
total_reference_instance_fields += cur_super->NumReferenceInstanceFieldsDuringLinking();
cur_super = cur_super->GetSuperClass();
}
if (super_class == nullptr) {
CHECK_EQ(total_reference_instance_fields, 1u) << PrettyDescriptor(klass.Get());
} else {
// Check that there is at least num_reference_fields other than Object.class.
CHECK_GE(total_reference_instance_fields, 1u + num_reference_fields)
<< PrettyClass(klass.Get());
}
}
if (!klass->IsVariableSize()) {
std::string temp;
DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp);
size_t previous_size = klass->GetObjectSize();
if (previous_size != 0) {
// Make sure that we didn't originally have an incorrect size.
CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp);
}
klass->SetObjectSize(size);
}
}
...
return true;
}
一个 RIL object 的内存数据:
(gdb) x /200x 0x12e27bb0
0x12e27bb0: 0x12ed7000 0x00000000 0x12ea97a0 0x12ea97b0
0x12e27bc0: 0x12ea95a0 0x12ea95d0 0x12ea9660 0x00000000
0x12e27bd0: 0x00000000 0x00000000 0x00000000 0x00000000
0x12e27be0: 0x12ea9710 0x00000000 0x12ea9700 0x12dc36a0
0x12e27bf0: 0x12ea95f0 0x12ea9670 0x00000000 0x12ea9720
0x12e27c00: 0x00000000 0x00000000 0x12ea9780 0x12ea9740
0x12e27c10: 0x00000000 0x12ea9620 0x12ea9610 0x00000000
0x12e27c20: 0x12ea96b0 0x00000000 0x12ea95c0 0x12ea9690
0x12e27c30: 0x12ea95b0 0x12ea9590 0x12ea9650 0x12ea9790
0x12e27c40: 0x12ea9580 0x12ea96a0 0x12ea96f0 0x00000000
0x12e27c50: 0x12ea9750 0x12ea9730 0x00000000 0x12ea96e0
0x12e27c60: 0x12ea9680 0x00000000 0x00000000 0x00000000
0x12e27c70: 0x12ea9770 0x00000000 0x00000000 0x12ea9570
0x12e27c80: 0x12d90a30 0x12ea9760 0x12ea96d0 0x12ea96c0
0x12e27c90: 0x00000000 0x00000000 0x12ea95e0 0x12ea9640
0x12e27ca0: 0x12ea9630 0x12ea9600 0x00000000 0x00000000
0x12e27cb0: 0x00000014 0x0000000d 0x12e8d4d8 0x12eb2d60
0x12e27cc0: 0x12ea59d0 0x12ea97d0 0x12e86c90 0x70791d58
0x12e27cd0: 0x00000000 0x12ea98c0 0x12eb55e0 0x12eb2d30
0x12e27ce0: 0x12edc1f0 0x12eb5550 0x12ee6070 0x12ea97c0
0x12e27cf0: 0x12e8d4a0 0x000000c8 0x00000003 0x00000002
0x12e27d00: 0x00000001 0x00000000 0x0000ea60 0x00000005
0x12e27d10: 0x00000001 0x00000000 0x00000000 0x00000000
...
0x12e27d20: 0x12ed7000 0x00000000 0x12ea9c40 0x12ea9c50
0x12e27d30: 0x12ea9a40 0x12ea9a70 0x12ea9b00 0x00000000
0x12e27d40: 0x00000000 0x00000000 0x00000000 0x00000000
0x12e27d50: 0x12ea9bb0 0x00000000 0x12ea9ba0 0x12dc36a0
(gdb) art_print_object 0x12e27bb0
$89 = (art::mirror::Class *) 0x12ed7000
com.android.internal.telephony.RIL
(gdb) art_print_object 0x12e27d20
$90 = (art::mirror::Class *) 0x12ed7000
com.android.internal.telephony.RIL
(gdb) p 0x12e27d20-0x12e27bb0
$95 = 368
RIL.java:
257 private static final int DEFAULT_WAKE_LOCK_TIMEOUT_MS = 60000;
762 mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT,
763 DEFAULT_WAKE_LOCK_TIMEOUT_MS);
可以判断 0x12e27d00+8 处对应的object field 为 mWakeLockTimeout;
以此可以延伸;