HandleScope
Handle
       在V8中,内存分配都是在V8的Heap中进行分配的,JavaScript的值和对象也都存放在V8的Heap中。这个Heap由V8独立的去维护,失去引用的对象将会被V8的GC掉并可以重新分配给其他对象。而Handle即是对Heap中对象的引用。V8为了对内存分配进行管理,GC需要对V8中的所有对象进行跟踪,而对象都是用Handle方式引用的,所以GC需要对Handle进行管理,这样GC就能知道Heap中一个对象的引用情况,当一个对象的Handle引用为发生改变的时候,GC即可对该对象进行回收(gc)或者移动。因此,V8编程中必须使用Handle去引用一个对象,而不是直接通过C++的方式去获取对象的引用,直接通过C++的方式去直接去引用一个对象,会使得该对象无法被V8管理。
       Handle分为Local和Persistent两种。从字面上就能知道,Local是局部的,它同时被HandleScope进行管理。persistent,类似与全局的,不受HandleScope的管理,其作用域可以延伸到不同的函数,而Local是局部的,作用域比较小。Persistent Handle对象需要Persistent::New, Persistent::Dispose配对使用,类似于C++中new和delete.Persistent::MakeWeak可以用来弱化一个Persistent Handle,如果一个对象的唯一引用Handle是一个Persistent,则可以使用MakeWeak方法来如果该引用,该方法可以出发GC对被引用对象的回收。
HandleScope
一个函数中,可以有很多Handle,而HandleScope则相当于用来装Handle(Local)的容器,当HandleScope生命周期结束的时候,Handle也将会被释放,会引起Heap中对象引用的更新。HandleScope是分配在栈上,不能通过New的方式进行创建。对于同一个作用域内可以有多个HandleScope,新的HandleScope将会覆盖上一个HandleScope,并对Local Handle进行管理。
// HandleScopes are scoped objects containing a number of Handles. They are used to allocate // handles, for these handles (and the objects contained within them) to be visible/roots for the // GC. It is most common to stack allocate HandleScopes using StackHandleScope. class PACKED(4) HandleScope { public: explicit HandleScope(size_t number_of_references) : link_(nullptr), number_of_references_(number_of_references) { } ~HandleScope() {} // Number of references contained within this handle scope. //对象引用的个数,在子类StackHandleScope实例化为对象的时候就已经确定下来了,即为kNumReferences uint32_t NumberOfReferences() const { return number_of_references_; } // Link to previous HandleScope or null. // 上一个节点 HandleScope* GetLink() const { return link_; } void SetLink(HandleScope* link) { DCHECK_NE(this, link); link_ = link; } // Offset of link within handle scope, used by generated code. static size_t ReferencesOffset(size_t pointer_size) { return pointer_size + sizeof(number_of_references_); } // Return backing storage used for references. // 返回引用起始地址 ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const { // caoming address = after const uint32_t number_of_references_; // address = this + sizeof(HandleScope*) + sizeof(number_of_references_) uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(sizeof(void*)); return reinterpret_cast<StackReference<mirror::Object>*>(address); } protected: // 单向链表,记录单个线程栈上的StackHandleScope,表头指向栈顶 HandleScope* link_; // thread该范围内对象引用个数 uint32_t number_of_references_; };
// Scoped handle storage of a fixed size that is usually stack allocated. template<size_t kNumReferences> class PACKED(4) StackHandleScope FINAL : public HandleScope { public: //存放的对象默认值fill_value为null inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self, mirror::Object* fill_value) : HandleScope(kNumReferences), self_(self), pos_(0) { // TODO: Figure out how to use a compile assert. DCHECK_EQ(&references_[0], &references_storage_[0]); for (size_t i = 0; i < kNumReferences; ++i) { SetReference(i, fill_value); } // 构造的时候进栈 self_->PushHandleScope(this); } inline StackHandleScope<kNumReferences>::~StackHandleScope() { //析构的时候出栈 HandleScope* top_handle_scope = self_->PopHandleScope(); DCHECK_EQ(top_handle_scope, this); } // 创建引用,并返回引用(Handle) template<class T> ALWAYS_INLINE Handle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { SetReference(pos_, object); Handle<T> h(GetHandle<T>(pos_)); pos_++; return h; } // Reference storage needs to be first as expected by the HandleScope layout. // 局部对象引用 StackReference<mirror::Object> references_storage_[kNumReferences]; // The thread that the stack handle scope is a linked list upon. The stack handle scope will // push and pop itself from this thread. Thread* const self_; // Position new handles will be created. // 表示该范围内对象引用index (<kNumReferences) size_t pos_; };
class Thread { //进栈函数,插入到链表头部 void Thread::PushHandleScope(HandleScope* handle_scope) { handle_scope->SetLink(tlsPtr_.top_handle_scope); /// CM set top hand boundary tlsPtr_.top_handle_scope = handle_scope; } //出栈函数 HandleScope* Thread::PopHandleScope() { HandleScope* handle_scope = tlsPtr_.top_handle_scope; DCHECK(handle_scope != nullptr); tlsPtr_.top_handle_scope = tlsPtr_.top_handle_scope->GetLink(); return handle_scope; } }
------------------------------------------------------------------------------------------------
FindClass() base type
static jclass JNI::FindClass(JNIEnv* env, const char* name) { CHECK_NON_NULL_ARGUMENT(name); Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); //Ljava/lang/String; std::string descriptor(NormalizeJniClassDescriptor(name)); ScopedObjectAccess soa(env); mirror::Class* c = nullptr; if (runtime->IsStarted()) { StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa))); c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader); } else { c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str()); } return soa.AddLocalReference<jclass>(c); }
mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor, Handle<mirror::ClassLoader> class_loader) { DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; DCHECK(self != nullptr); self->AssertNoPendingException(); if (descriptor[1] == '\0') { // only the descriptors of primitive types should be 1 character long, also avoid class lookup // for primitive classes that aren't backed by dex files. return FindPrimitiveClass(descriptor[0]); } const size_t hash = ComputeModifiedUtf8Hash(descriptor); // Find the class in the loaded classes table. mirror::Class* klass = LookupClass(self, descriptor, hash, class_loader.Get()); if (klass != nullptr) { return EnsureResolved(self, descriptor, klass); } // Class is not yet loaded. if (descriptor[0] == '[') { return CreateArrayClass(self, descriptor, hash, class_loader); } else if (class_loader.Get() == nullptr) { // The boot class loader, search the boot class path. ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); if (pair.second != nullptr) { return DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first, *pair.second); } else { // The boot class loader is searched ahead of the application class loader, failures are // expected and will be wrapped in a ClassNotFoundException. Use the pre-allocated error to // trigger the chaining with a proper stack trace. mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); self->SetException(pre_allocated); return nullptr; } } else { ScopedObjectAccessUnchecked soa(self); mirror::Class* cp_klass; if (FindClassInPathClassLoader(soa, self, descriptor, hash, class_loader, &cp_klass)) { // The chain was understood. So the value in cp_klass is either the class we were looking // for, or not found. if (cp_klass != nullptr) { return cp_klass; } // TODO: We handle the boot classpath loader in FindClassInPathClassLoader. Try to unify this // and the branch above. TODO: throw the right exception here. // We'll let the Java-side rediscover all this and throw the exception with the right stack // trace. } if (Runtime::Current()->IsAotCompiler()) { // Oops, compile-time, can't run actual class-loader code. mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); self->SetException(pre_allocated); return nullptr; } ScopedLocalRef<jobject> class_loader_object(soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get())); std::string class_name_string(DescriptorToDot(descriptor)); ScopedLocalRef<jobject> result(soa.Env(), nullptr); { ScopedThreadStateChange tsc(self, kNative); ScopedLocalRef<jobject> class_name_object(soa.Env(), soa.Env()->NewStringUTF(class_name_string.c_str())); if (class_name_object.get() == nullptr) { DCHECK(self->IsExceptionPending()); // OOME. return nullptr; } CHECK(class_loader_object.get() != nullptr); result.reset(soa.Env()->CallObjectMethod(class_loader_object.get(), WellKnownClasses::java_lang_ClassLoader_loadClass, class_name_object.get())); } if (self->IsExceptionPending()) { // If the ClassLoader threw, pass that exception up. return nullptr; } else if (result.get() == nullptr) { // broken loader - throw NPE to be compatible with Dalvik ThrowNullPointerException(StringPrintf("ClassLoader.loadClass returned null for %s", class_name_string.c_str()).c_str()); return nullptr; } else { // success, return mirror::Class* return soa.Decode<mirror::Class*>(result.get()); } } UNREACHABLE(); }
mirror::Class* ClassLinker::FindPrimitiveClass(char type) { switch (type) { case 'B': return GetClassRoot(kPrimitiveByte); case 'C': return GetClassRoot(kPrimitiveChar); case 'D': return GetClassRoot(kPrimitiveDouble); case 'F': return GetClassRoot(kPrimitiveFloat); case 'I': return GetClassRoot(kPrimitiveInt); case 'J': return GetClassRoot(kPrimitiveLong); case 'S': return GetClassRoot(kPrimitiveShort); case 'Z': return GetClassRoot(kPrimitiveBoolean); case 'V': return GetClassRoot(kPrimitiveVoid); default: break; } std::string printable_type(PrintableChar(type)); ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str()); return nullptr; }
class ClassLinker { enum ClassRoot { kJavaLangClass, kJavaLangObject, kClassArrayClass, kObjectArrayClass, kJavaLangString, kJavaLangDexCache, kJavaLangRefReference, kJavaLangReflectArtField, kJavaLangReflectArtMethod, kJavaLangReflectProxy, kJavaLangStringArrayClass, kJavaLangReflectArtFieldArrayClass, kJavaLangReflectArtMethodArrayClass, kJavaLangClassLoader, kJavaLangThrowable, kJavaLangClassNotFoundException, kJavaLangStackTraceElement, kPrimitiveBoolean, kPrimitiveByte, kPrimitiveChar, kPrimitiveDouble, kPrimitiveFloat, kPrimitiveInt, kPrimitiveLong, kPrimitiveShort, kPrimitiveVoid, kBooleanArrayClass, kByteArrayClass, kCharArrayClass, kDoubleArrayClass, kFloatArrayClass, kIntArrayClass, kLongArrayClass, kShortArrayClass, kJavaLangStackTraceElementArrayClass, kClassRootsMax, }; } inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); mirror::Class* klass = class_roots->Get(class_root); return klass; }
Primitive类型如何初始化
mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) { mirror::Class* klass = AllocClass(self, mirror::Class::PrimitiveClassSize()); if (UNLIKELY(klass == nullptr)) { return nullptr; } return InitializePrimitiveClass(klass, type); } mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) { CHECK(primitive_class != nullptr); // Must hold lock on object when initializing. Thread* self = Thread::Current(); StackHandleScope<1> hs(self); Handle<mirror::Class> h_class(hs.NewHandle(primitive_class)); ObjectLock<mirror::Class> lock(self, h_class); primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract); primitive_class->SetPrimitiveType(type); primitive_class->SetStatus(mirror::Class::kStatusInitialized, self); const char* descriptor = Primitive::Descriptor(type); mirror::Class* existing = InsertClass(descriptor, primitive_class, ComputeModifiedUtf8Hash(descriptor)); CHECK(existing == nullptr) << "InitPrimitiveClass(" << type << ") failed"; return primitive_class; }
                    
                
                
            
        
浙公网安备 33010602011771号