这里JNI返回的实际是间接引用,不是object对象地址.
比如这里返回的jclass是0x5c6, 这个间接引用实际代表的object是0x732359f8
template
inline T JNIEnvExt::AddLocalReference(mirror::Object* obj) {
IndirectRef ref = locals.Add(local_ref_cookie, obj);
return reinterpret_cast(ref);
}
local.Add()的实现为
87IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) {
88 IRTSegmentState prevState;
89 prevState.all = cookie;
90 size_t topIndex = segment_state_.parts.topIndex;
91
92 CHECK(obj != NULL);
93 VerifyObject(obj);
94 DCHECK(table_ != NULL);
95 DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);
96
97 if (topIndex == max_entries_) {
98 LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow "
99 << "(max=" << max_entries_ << ")\n"
100 << MutatorLockedDumpable(*this);
101 }
102
103 // We know there's enough room in the table. Now we just need to find
104 // the right spot. If there's a hole, find it and fill it; otherwise,
105 // add to the end of the list.
106 IndirectRef result;
107 int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles;
108 size_t index;
109 if (numHoles > 0) {
110 DCHECK_GT(topIndex, 1U);
111 // Find the first hole; likely to be near the end of the list.
112 IrtEntry* pScan = &table_[topIndex - 1];
113 DCHECK(!pScan->GetReference()->IsNull());
114 --pScan;
115 while (!pScan->GetReference()->IsNull()) {
116 DCHECK_GE(pScan, table_ + prevState.parts.topIndex);
117 --pScan;
118 }
119 index = pScan - table_;
120 segment_state_.parts.numHoles--;
121 } else {
122 // Add to the end.
123 index = topIndex++;
124 segment_state_.parts.topIndex = topIndex;
125 }
126 table_[index].Add(obj);
127 result = ToIndirectRef(index);
128 if (false) {
129 LOG(INFO) << "+++ added at " << ExtractIndex(result) << " top=" << segment_state_.parts.topIndex
130 << " holes=" << segment_state_.parts.numHoles;
131 }
132
133 DCHECK(result != NULL);
134 return result;
135}
里面最重要的转换如下:
result = ToIndirectRef(index);
函数实现如下:
364 IndirectRef ToIndirectRef(uint32_t tableIndex) const {
365 DCHECK_LT(tableIndex, 65536U);
366 uint32_t serialChunk = table_[tableIndex].GetSerial();
367 uintptr_t uref = (serialChunk << 20) | (tableIndex << 2) | kind_;
368 return reinterpret_cast(uref);
369 }
看到这里就一目了然了实际对象存储在IndirectReferenceTable的table_[]数组中
返回的jClass实际是serial/table_idx/ref type三者的OR值
举例如下
0x74deaa3000:0x000000010x7012e9100x6fb9d7200x00000000
0x74deaa3010:0x000000020x000000000x6fbd6d200x732333c8
0x74deaa3020:0x000000000x732358880x6fba70b80x6fbd3ca0
0x74deaa3030:0x000000000x732358c00x6fb4c3c80x6fbbb758
table_中每条entry四个word,第1个word是serial,表示当前正在使用的index(0/1/2)
后面3个word用于存储实际的object, 具体使用哪个由前面的serial指定
黑体部分表示当前使用的object
下次使用时,再通过ExtractIndex()转换回来,就使用到真正的object了.
另外,art/mirror/下面的很多类实际就是Java类的c++版本实现, 供ART虚拟机使用.
Java对象的内存布局以art::mirror里面声明的成员的顺序依次进行存储,成员的大小是一致的,但声明顺序有可能不同.