引言
在分析ART虚拟机的中对象模型时,发现Mirror Object类中引用的其他object指针/对象头的指向Class的指针,都使用了HeapReference来包装,都是HeapReference类型,而HeapReference
类只是对uint32_t
类型的值进行包装,在64位系统是8字节的指针,4字节怎么装得下去的,然后发现他对指针进行了压缩:
emplate<class MirrorType>
class MANAGED HeapReference {
private:
using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>;
public:
HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {}
template <bool kIsVolatile = false>
MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
return Compression::Decompress(
kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData());
}
template <bool kIsVolatile = false>
void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
if (kIsVolatile) {
reference_.store(Compression::Compress(other), std::memory_order_seq_cst);
} else {
reference_.StoreJavaData(Compression::Compress(other));
}
}
template <bool kIsVolatile = false>
void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
void Clear() {
reference_.StoreJavaData(0);
DCHECK(IsNull());
}
bool IsNull() const {
return reference_.LoadJavaData() == 0;
}
static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
return HeapReference<MirrorType>(mirror_ptr);
}
bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr)
REQUIRES_SHARED(Locks::mutator_lock_);
private:
explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
: reference_(Compression::Compress(mirror_ptr)) {}
// The encoded reference to a mirror::Object. Atomically updateable.
Atomic<uint32_t> reference_;
};
这个类型保存的reference_
的是通过PtrCompression
进行的压缩
template<bool kPoisonReferences, class MirrorType>
class PtrCompression {
public:
// Compress reference to its bit representation.
static uint32_t Compress(MirrorType* mirror_ptr) {
uint32_t as_bits = reinterpret_cast32<uint32_t>(mirror_ptr);
return kPoisonReferences ? -as_bits : as_bits;
}
// Uncompress an encoded reference from its bit representation.
static MirrorType* Decompress(uint32_t ref) {
uint32_t as_bits = kPoisonReferences ? -ref : ref;
return reinterpret_cast32<MirrorType*>(as_bits);
}
// Convert an ObjPtr to a compressed reference.
static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
};
这个32位无符号数,可以通过Decompress()
函数强制转换为Java对象的指针,代码如下:
template <bool kIsVolatile = false>
MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
return Compression::Decompress(
kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData());
}
ArtMethod的成员变量declaring_class_是一个uint32_t,这块为什么要用uint32_t的代替,而且后面用reinterpret_cast把这个uint32_转为了一个指针,但是这里面指针的大小不应该是8字节64位的吗 它又是怎么转的?
不会, 它只要保证ObjectReference引用的东西在4gb空间内就行, 其它的不受影响.
参考http://androidxref.com/7.1.1_r6/xref/art/runtime/runtime.h#728,
Special low 4gb pool for compiler linear alloc. We need ArtFields to be in low 4gb if we are compiling using a 32 bit image on a 64 bit compiler in case we resolve things in the image since the field arrays are int arrays in this case.
参考文章
https://juejin.cn/post/7270871863160733752
https://www.pqpo.me/2017/07/07/hotfix-method-hook/#comment-265