当前位置: 首页 > wzjs >正文

做酒的网站名字大全企业网站有哪些

做酒的网站名字大全,企业网站有哪些,网站开发设计书,什么是推广员目录 一,概述 二,ART运行时的入口 一,概述 既然ART运行时执行的都是翻译DEX字节码后得到的本地机器指令了,为什么还需要在OAT文件中包含DEX文件,并且将它加载到内存去呢?这是因为ART运行时提供了Java虚拟机接口,而要实现Java虚…

目录

一,概述

二,ART运行时的入口


一,概述

既然ART运行时执行的都是翻译DEX字节码后得到的本地机器指令了,为什么还需要在OAT文件中包含DEX文件,并且将它加载到内存去呢?这是因为ART运行时提供了Java虚拟机接口,而要实现Java虚拟机接口不得不依赖于DEX文件

ART运行时查找类方法的本地机器指令的过程

为了方便描述,我们将DEX文件中描述的类和方法称为DEX类(Dex Class)和DEX方法(Dex Method),而将在OAT文件中描述的类和方法称为OAT类(Oat Class)和OAT方法(Oat Method)。接下来我们还会看到,ART运行时在内部又会使用另外两个不同的术语来描述类和方法,其中将类描述为Class,而将类方法描述为ArtMethod。

       在图1中,为了找到一个类方法的本地机器指令,我们需要执行以下的操作:

       1. 在DEX文件中找到目标DEX类的编号,并且以这个编号为索引,在OAT文件中找到对应的OAT类。

       2. 在DEX文件中找到目标DEX方法的编号,并且以这个编号为索引,在上一步找到的OAT类中找到对应的OAT方法。

       3. 使用上一步找到的OAT方法的成员变量begin_和code_offset_,计算出该方法对应的本地机器指令

二,ART运行时的入口

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{ALOGD(">>>>>> START %s uid %d <<<<<<\n",className != NULL ? className : "(unknown)", getuid());static const String8 startSystemServer("start-system-server");/** 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*/for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /android does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}//const char* kernelHack = getenv("LD_ASSUME_KERNEL");//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);/* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) < 0) {‘’‘’‘’‘’‘’‘’‘’‘’‘’‘’
}

首先是通过调用函数startVm创建了一个Java虚拟机mJavaVM及其JNI接口env。这个Java虚拟机实际上就是ART运行时。在接下来的描述中,我们将不区分ART虚拟机和ART运行时,并且认为它们表达的是同一个概念。获得了ART虚拟机的JNI接口之后,就可以通过它提供的函数FindClass和GetStaticMethodID来加载com.android.internal.os.ZygoteInit类及其静态成员函数main。于是,最后就可以再通过JNI接口提供的函数CallStaticVoidMethod来调用com.android.internal.os.ZygoteInit类的静态成员函数main,以及进行到ART虚拟机里面去运行。
 在分析JNI接口FindClass和GetStaticMethodID的实现之前,我们先要讲清楚JNI接口是如何创建的

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
}

JNI类的静态成员函数FindClass的实现如下所示

/Volumes/aosp/android-8.1.0_r52/art/runtime/jni_internal.cc

static jclass FindClass(JNIEnv* env, const char* name) {CHECK_NON_NULL_ARGUMENT(name);Runtime* runtime = Runtime::Current();ClassLinker* class_linker = runtime->GetClassLinker();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);}

NI类的静态成员函数FindClass首先是判断ART运行时是否已经启动起来。如果已经启动,那么就通过调用函数GetClassLoader来获得当前线程所关联的ClassLoader,并且以此为参数,调用前面获得的ClassLinker对象的成员函数FindClass来加载由参数name指定的类。一般来说,当前线程所关联的ClassLoader就是当前正在执行的类方法所关联的ClassLoader,即用来加载当前正在执行的类的ClassLoader。如果ART虚拟机还没有开始执行类方法,就像我们现在这个场景,那么当前线程所关联的ClassLoader实际上就系统类加载器,即SystemClassLoader。

       如果ART运行时还没有启动,那么这时候只可以加载系统类。这个通过前面获得的ClassLinker对象的成员函数FindSystemClass来实现的。在我们这个场景中,ART运行时已经启动,因此,接下来我们就继续分析ClassLinker类的成员函数FindClass的实现。

        ClassLinker类的成员函数FindClass的实现如下所示:


 /Volumes/aosp/android-8.1.0_r52/art/runtime/class_linker.cc

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();self->PoisonObjectPointers();  // For DefineClass, CreateArrayClass, etc...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.ObjPtr<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] != '[' && class_loader == nullptr) {// Non-array class and 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,ScopedNullHandle<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.ObjPtr<mirror::Throwable> pre_allocated =Runtime::Current()->GetPreAllocatedNoClassDefFoundError();self->SetException(pre_allocated);return nullptr;}}ObjPtr<mirror::Class> result_ptr;bool descriptor_equals;if (descriptor[0] == '[') {result_ptr = CreateArrayClass(self, descriptor, hash, class_loader);DCHECK_EQ(result_ptr == nullptr, self->IsExceptionPending());DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(descriptor));descriptor_equals = true;} else {ScopedObjectAccessUnchecked soa(self);bool known_hierarchy =FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result_ptr);if (result_ptr != nullptr) {// The chain was understood and we found the class. We still need to add the class to// the class table to protect from racy programs that can try and redefine the path list// which would change the Class<?> returned for subsequent evaluation of const-class.DCHECK(known_hierarchy);DCHECK(result_ptr->DescriptorEquals(descriptor));descriptor_equals = true;} else {// Either the chain wasn't understood or the class wasn't found.//// If the chain was understood but we did not find the class, let the Java-side// rediscover all this and throw the exception with the right stack trace. Note that// the Java-side could still succeed for racy programs if another thread is actively// modifying the class loader's path list.if (!self->CanCallIntoJava()) {// Oops, we can't call into java so we can't run actual class-loader code.// This is true for e.g. for the compiler (jit or aot).ObjPtr<mirror::Throwable> pre_allocated =Runtime::Current()->GetPreAllocatedNoClassDefFoundError();self->SetException(pre_allocated);return nullptr;}
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
}

ClassLinker类的成员函数FindClass首先是调用另外一个成员函数LookupClass来检查参数descriptor指定的类是否已经被加载过。如果是的话,那么ClassLinker类的成员函数LookupClass就会返回一个对应的Class对象,这个Class对象接着就会返回给调用者,表示加载已经完成
 

知道了参数descriptor指定的类定义在哪一个DEX文件之后,就可以通过ClassLinker类的另外一个成员函数DefineClass来从中加载它了。接下来,我们就继续分析ClassLinker类的成员函数DefineClass的实现

mirror::Class* ClassLinker::DefineClass(Thread* self,const char* descriptor,size_t hash,Handle<mirror::ClassLoader> class_loader,const DexFile& dex_file,const DexFile::ClassDef& dex_class_def) {StackHandleScope<3> hs(self);auto klass = hs.NewHandle<mirror::Class>(nullptr);// Load the class from the dex file.if (UNLIKELY(!init_done_)) {// finish up init of hand crafted class_roots_if (strcmp(descriptor, "Ljava/lang/Object;") == 0) {klass.Assign(GetClassRoot(kJavaLangObject));} else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) {klass.Assign(GetClassRoot(kJavaLangClass));} else if (strcmp(descriptor, "Ljava/lang/String;") == 0) {klass.Assign(GetClassRoot(kJavaLangString));} else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) {klass.Assign(GetClassRoot(kJavaLangRefReference));} else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) {klass.Assign(GetClassRoot(kJavaLangDexCache));} else if (strcmp(descriptor, "Ldalvik/system/ClassExt;") == 0) {klass.Assign(GetClassRoot(kDalvikSystemClassExt));}}if (klass == nullptr) {// Allocate a class with the status of not ready.// Interface object should get the right size here. Regular class will// figure out the right size later and be replaced with one of the right// size when the class becomes resolved.klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));}if (UNLIKELY(klass == nullptr)) {self->AssertPendingOOMException();return nullptr;}

调用ClassLinker类的成员函数DefineClass的时候,如果ClassLinker正处于初始化过程,即其成员变量init_done_的值等于false,并且参数descriptor描述的是特定的内部类,那么就将本地变量klass指向它们,其余情况则会通过成员函数AllocClass为其分配存储空间,以便后面通过成员函数LoadClass进行初始化
 

接下来,我们主要分析ClassLinker类的成员函数LoadClass的实现,以便可以了解类的加载过程。

        ClassLinker类的成员函数LoadClass的实现如下所示

void ClassLinker::LoadClass(Thread* self,const DexFile& dex_file,const DexFile::ClassDef& dex_class_def,Handle<mirror::Class> klass) {const uint8_t* class_data = dex_file.GetClassData(dex_class_def);if (class_data == nullptr) {return;  // no fields or methods - for example a marker interface}LoadClassMembers(self, dex_file, class_data, klass);
}
void ClassLinker::LoadClassMembers(Thread* self,const DexFile& dex_file,const uint8_t* class_data,Handle<mirror::Class> klass) {{// Note: We cannot have thread suspension until the field and method arrays are setup or else// Class::VisitFieldRoots may miss some fields or methods.ScopedAssertNoThreadSuspension nts(__FUNCTION__);// Load static fields.// We allow duplicate definitions of the same field in a class_data_item// but ignore the repeated indexes here, b/21868015.LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());ClassDataItemIterator it(dex_file, class_data);LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,allocator,it.NumStaticFields());size_t num_sfields = 0;uint32_t last_field_idx = 0u;for (; it.HasNextStaticField(); it.Next()) {uint32_t field_idx = it.GetMemberIndex();DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {DCHECK_LT(num_sfields, it.NumStaticFields());LoadField(it, klass, &sfields->At(num_sfields));++num_sfields;last_field_idx = field_idx;}}// Load instance fields.LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,allocator,it.NumInstanceFields());size_t num_ifields = 0u;last_field_idx = 0u;for (; it.HasNextInstanceField(); it.Next()) {uint32_t field_idx = it.GetMemberIndex();DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {DCHECK_LT(num_ifields, it.NumInstanceFields());LoadField(it, klass, &ifields->At(num_ifields));++num_ifields;last_field_idx = field_idx;}}
'''''''''''''''
}

们首先要明确一下各个参数的含义:

       dex_file: 类型为DexFile,描述要加载的类所在的DEX文件。

       dex_class_def: 类型为ClassDef,描述要加载的类在DEX文件里面的信息。

       klass: 类型为Class,描述加载完成的类。

       class_loader:  类型为ClassLoader,描述所使用的类加载器
 ClassLinker类的成员函数LoadClass的任务就是要用dex_file、dex_class_def、class_loader三个参数包含的相关信息设置到参数klass描述的Class对象去,以便可以得到一个完整的已加载类信息。

static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,const char* name, const char* sig, bool is_static)REQUIRES_SHARED(Locks::mutator_lock_) {ObjPtr<mirror::Class> c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class>(jni_class));if (c == nullptr) {return nullptr;}ArtMethod* method = nullptr;auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();if (c->IsInterface()) {method = c->FindInterfaceMethod(name, sig, pointer_size);} else {method = c->FindClassMethod(name, sig, pointer_size);}if (method == nullptr || method->IsStatic() != is_static) {ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static");return nullptr;}return jni::EncodeArtMethod(method);
}

函数FindMethodID的执行过程如下所示:

       1. 将参数jni_class的值转换为一个Class指针c,因此就可以得到一个Class对象,并且通过ClassLinker类的成员函数EnsureInitialized确保该Class对象描述的类已经初始化。

       2. Class对象c描述的类在加载的过程中,经过解析已经关联上一系列的成员函数。这些成员函数可以分为两类:Direct和Virtual。Direct类的成员函数包括所有的静态成员函数、私有成员函数和构造函数,而Virtual则包括所有的虚成员函数。因此:

           2.1. 当参数is_static的值等于true时,那么就表示要查找的是静态成员函数,这时候就在Class对象c描述的类的关联的Direct成员函数列表中查找参数name和sig对应的成员函数。这是通过调用Class类的成员函数FindDirectMethod来实现的。

           2.2. 当参数is_static的值不等于true时,那么就表示要查找的是虚拟成员函数或者非静态的Direct成员函数,这时候先在Class对象c描述的类的关联的Virtual成员函数列表中查找参数name和sig对应的成员函数。这是通过调用Class类的成员函数FindVirtualMethod来实现的。如果找不到对应的虚拟成员函数,那么再在Class对象c描述的类的关联的Direct成员函数列表中查找参数name和sig对应的成员函数。

       3. 经过前面的查找过程,如果都不能在Class对象c描述的类中找到与参数name和sig对应的成员函数,那么就抛出一个NoSuchMethodError异常。否则的话,就将查找得到的ArtMethod对象封装成一个jmethodID值返回给调用者。

       也就是说,我们通过调用JNI接口GetStaticMethodID获得的不透明jmethodID值指向的实际上是一个ArtMethod对象。得益于前面的类加载过程,当我们获得了一个ArtMethod对象之后,就可以轻松地得到它的本地机器指令入口,进而对它进行执行
 

http://www.dtcms.com/wzjs/498686.html

相关文章:

  • 网页设计制作个人网站搜索引擎和浏览器
  • 赤峰网站建设red短视频营销成功案例
  • 做网站插入文档特殊字符强强seo博客
  • 做网站怎样赚到钱百度账号怎么改用户名
  • 做网站需要的语言湖南seo优化服务
  • 龙岩做网站改版找哪家公司网站搜索引擎优化技术
  • 泉州做网站qzxiaolv百度人工服务
  • 青岛房产网站建设google在线代理
  • 网站建设微信版网络推广怎么找客户
  • 专做排名的网站谷歌搜索引擎google
  • 怎么做自己的企业网站优化seo报价
  • 网站管理公司注册网站免费注册
  • 商城网站建设优化推广seo公司品牌哪家好
  • 邯郸网站制作百度一下你就知道啦
  • 做哪个网站比较有流量江西优化中心
  • 上传视频网站开发刷排名有百度手机刷排名
  • 沈阳关键词网站排名咸阳seo
  • 昆明做烤瓷牙哪去柏德L网站外包公司软件开发
  • 长春网站开发培训价格流量精灵官网
  • 怎样做网站平台网络营销是做什么的
  • 有没有人一起做网站今日热点新闻事件摘抄2022
  • 可靠的上海网站建设公免费发帖平台
  • 门户网站建设内容b2b平台推广
  • 佛山网站建设 骏域网站百度投诉中心在线申诉
  • 如何做产品网站建设seo网站免费优化软件
  • 做宽屏网站建网站建设
  • 受欢迎的扬中网站建设百度地图在线查询
  • 免费注册网站域名一个完整的营销策划方案范文
  • 做设计网站的工作怎么样长沙网站seo哪家公司好
  • 西安做网站建设的aso关键词优化计划