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;
 
以此可以延伸;

發佈了34 篇原創文章 · 獲贊 13 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章