Java Class/Object Memory layout

1. Java class memory layout

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<Object>);                              // 加上 Reference类型的 static field 占用的内存大小,sizeof(HeapReference<Object>)的值为 4;num_ref_static_fields 对应
                                                                                              // 上面 art::mirror::Class 的 num_reference_static_fields_ 成员的值;
 
  if (!IsAligned<8>(size) && num_64bit_static_fields > 0) {                                   // 如果 当前java类存在8字节的的static成员,且上面计算完成的size不是8字节对其,则进行8字节对齐和把gap填充其他static成员的操作;
    uint32_t gap = 8 - (size & 0x7);
    size += gap;  // will be padded
    // Shuffle 4-byte fields forward.
    while (gap >= sizeof(uint32_t) && num_32bit_static_fields != 0) {
      --num_32bit_static_fields;
      gap -= sizeof(uint32_t);
    }
    // Shuffle 2-byte fields forward.
    while (gap >= sizeof(uint16_t) && num_16bit_static_fields != 0) {
      --num_16bit_static_fields;
      gap -= sizeof(uint16_t);
    }
    // Shuffle byte fields forward.
    while (gap >= sizeof(uint8_t) && num_8bit_static_fields != 0) {
      --num_8bit_static_fields;
      gap -= sizeof(uint8_t);
    }
  }
  // Guaranteed to be at least 4 byte aligned. No need for further alignments.
  // Space used for primitive static fields.
  size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) +  // 把剩余的static field数据占用的空间计算进入class 的大小 size中;
  num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t);
  return size;
}

  • invoke-static 是类静态方法的调用,编译时,静态确定的;
  • invoke-virtual 虚方法调用,调用的方法运行时确认实际调用,和实例引用的实际对象有关,动态确认的,一般是带有修饰符protected或public的方法;
  • invoke-direct 没有被覆盖方法的调用,即不用动态根据实例所引用的调用,编译时,静态确认的,一般是private或<init>方法;
  • invoke-super 直接调用父类的虚方法,编译时,静态确认的。
  • invokeinterface 调用接口方法,调用的方法运行时确认实际调用,即会在运行时才确定一个实现此接口的对象。

只有通过 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 = {
  <art::mirror::Object> = {
    static kVTableLength = 0xb,
    static hash_code_seed = {
      <std::__1::atomic<unsigned int>> = {
        <std::__1::__atomic_base<unsigned int, true>> = {
          <std::__1::__atomic_base<unsigned int, false>> = {
            __a_ = 0x1f02f126
          }, <No data fields>}, <No data fields>}, <No data fields>},
    klass_ = {
      <art::mirror::ObjectReference<false, art::mirror::Class>> = {
        reference_ = 0x707f1d88
      }, <No data fields>},
    monitor_ = 0x0
  },
  members of art::mirror::Class:
  static kClassWalkSuper = 0xc0000000,
  static kImtSize = 0x40,
  annotation_type_ = {
    <art::mirror::ObjectReference<false, art::mirror::Object>> = {
      reference_ = 0x0
    }, <No data fields>},
  class_loader_ = {
    <art::mirror::ObjectReference<false, art::mirror::ClassLoader>> = {
      reference_ = 0x0
    }, <No data fields>},
  component_type_ = {
    <art::mirror::ObjectReference<false, art::mirror::Class>> = {
      reference_ = 0x0
    }, <No data fields>},
  dex_cache_ = {
    <art::mirror::ObjectReference<false, art::mirror::DexCache>> = {
      reference_ = 0x715990c8
    }, <No data fields>},
  iftable_ = {
    <art::mirror::ObjectReference<false, art::mirror::IfTable>> = {
      reference_ = 0x0
    }, <No data fields>},
  name_ = {
    <art::mirror::ObjectReference<false, art::mirror::String>> = {
      reference_ = 0x0
    }, <No data fields>},
  super_class_ = {
    <art::mirror::ObjectReference<false, art::mirror::Class>> = {
      reference_ = 0x707f27f0
    }, <No data fields>},
  verify_error_ = {
    <art::mirror::ObjectReference<false, art::mirror::Object>> = {
      reference_ = 0x0
    }, <No data fields>},
  vtable_ = {
    <art::mirror::ObjectReference<false, art::mirror::PointerArray>> = {
---Type <return> to continue, or q <return> to quit---
      reference_ = 0x0
    }, <No data fields>},
  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_ = {
      <art::mirror::ObjectReference<false, art::mirror::Object>> = {
        reference_ = 0x707f1d88
      }, <No data fields>}
  }
}

2. Java object memory layout

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<mirror::Class> klass,
                             bool is_static,
                             size_t* class_size) {
  self->AllowThreadSuspension();
  const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
  LengthPrefixedArray<ArtField>* 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<ArtField*> 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<sizeof(mirror::HeapReference<mirror::Object>)>(
        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<mirror::Object>));
    grouped_and_sorted_fields.pop_front();
    num_reference_fields++;
    field->SetOffset(field_offset);
    field_offset = MemberOffset(field_offset.Uint32Value() +
                                sizeof(mirror::HeapReference<mirror::Object>));
  }
  // 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;
 
以此可以延伸;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值