ART的反射调用(二)--创建对象实例

通过反射创建实例的用法是:

Class<?> clz = Class.forName("com.xx.xx");
Constructor<?> constructor = clz.getConstructor(String.Class);
Object obj = constructor.newInstance("xx");

通过Class.forName在上一篇ART的反射调用(一)中已经分析

一. Class.getConstructor

public Constructor<T> getConstructor(Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
    return getConstructor0(parameterTypes, Member.PUBLIC);
}

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                      int which) throws NoSuchMethodException{
    if (parameterTypes == null) {
        parameterTypes = EmptyArray.CLASS;
    }
    for (Class<?> c : parameterTypes) {
        if (c == null) {
            throw new NoSuchMethodException("parameter type is null");
        }
    }
    //核心调用
    Constructor<T> result = getDeclaredConstructorInternal(parameterTypes);

    if (result == null || which == Member.PUBLIC && !Modifier.isPublic(result.getAccessFlags())) {
        throw new NoSuchMethodException("<init> " + Arrays.toString(parameterTypes));
    }
    return result;
}

private native Constructor<T> getDeclaredConstructorInternal(Class<?>[] args);

1.1 getDeclaredConstructorInternal

getDeclaredConstructorInternal的实现在/art/runtime/native/java_lang_Class.cc

static jobject Class_getDeclaredConstructorInternal(
        JNIEnv* env, jobject javaThis, jobjectArray args) {
    ScopedFastNativeObjectAccess soa(env);
    //核心调用,[1.2]
    mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal(
          soa.Self(),
          //将Java层的Class对象转换为mirror::Class指针
          DecodeClass(soa, javaThis),
          //将Java层的数组转换为存放mirror::Class指针的数组
          soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
    return soa.AddLocalReference<jobject>(result);
}

1.2 mirror::Class::GetDeclaredConstructorInternal

GetDeclaredConstructorInternal声明在/art/runtime/mirror/class.h

template <bool kTransactionActive = false>
static Constructor* GetDeclaredConstructorInternal(Thread* self,
                                                 mirror::Class* klass,
                                                 mirror::ObjectArray<mirror::Class>* args)
  SHARED_REQUIRES(Locks::mutator_lock_);

NOTE:kTransactionActive默认为false

这个方法的实现在/art/runtime/mirror/class.cc

template <bool kTransactionActive>
mirror::Constructor* Class::GetDeclaredConstructorInternal(
          Thread* self,
          mirror::Class* klass,
          mirror::ObjectArray<mirror::Class>* args) {
    StackHandleScope<1> hs(self);
    //kTransactionActive默认为false
    const size_t pointer_size = kTransactionActive
                                    ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
                                    : sizeof(void*);
    //[1.3]
    ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), pointer_size);
    //[1.4]
    return result != nullptr
        ? mirror::Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
        : nullptr;
}

1.3 mirror::Class::GetDeclaredConstructor

ArtMethod* Class::GetDeclaredConstructor(Thread* self,
        Handle<mirror::ObjectArray<mirror::Class>> args, size_t pointer_size) {
    //迭代每一个Direct Method, [1.3.1]
    //m是ArtMethod     
    for (auto& m : GetDirectMethods(pointer_size)) {
        // 跳过<clinit>方法, <clinit>是类的初始化方法,不是构造函数,所以跳过
        if (m.IsStatic() || !m.IsConstructor()) {
            continue;
        }
        // May cause thread suspension and exceptions.
        // GetInterfaceMethodIfProxy方法一般情况下都是直接返回m的this引用
        // EqualParameters方法用来判断传入的参数是否与方法本身的参数相同
        if (m.GetInterfaceMethodIfProxy(sizeof(void*))->EqualParameters(args)) {
            return &m;
        }
        if (UNLIKELY(self->IsExceptionPending())) {
            return nullptr;
        }
    }
    return nullptr;
}

1.3.1 mirror::Class::GetDirectMethods

inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) {
    CheckPointerSize(pointer_size);
    return GetDirectMethodsSliceUnchecked(pointer_size).AsRange();
}

可以看到,GetDirectMethods实质上就是封装调用了GetDirectMethodsSliceUnchecked,GetDirectMethodsSliceUnchecked定义在/art/runtime/mirror/class-inl.h

///art/runtime/mirror/class-inl.h
inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(size_t pointer_size) {
    return ArraySlice<ArtMethod>(GetMethodsPtr(), //返回LengthPrefixedArray<ArtMethod>*,实质上封装的是当前类的Method数组指针
                                 GetDirectMethodsStartOffset(),//返回Direct Method的起始偏移地址
                                 GetVirtualMethodsStartOffset(),//返回Virtual Method的起始偏移地址
                                 ArtMethod::Size(pointer_size),//pointer_size实质上是sizeof(void *)
                                 ArtMethod::Alignment(pointer_size));
}

ArraySlice定义在/art/runtime/base/array_slice.h

/art/runtime/base/array_slice.h
ArraySlice(LengthPrefixedArray<T>* array,
             uint32_t start_offset,
             uint32_t end_offset,
             size_t element_size = sizeof(T),
             size_t alignment = alignof(T))
      : array_(nullptr),
        size_(end_offset - start_offset),//Virtual Method的起始地址减去Direct Method的起始地址,这一段存储的全部是Direct Method
        element_size_(element_size) {//每一个element的大小都是sizeof(void *)
    ...
    if (size_ != 0) {
      ...
      //T实质上是ArtMethod, 而array_的声明是T* array_,所以array_实质是ArtMethod*
      //实际就是将array_指向ArtMethod数组
      array_ = &array->At(start_offset, element_size_, alignment);
    }
}

//AsRange的作用是获取所有Direct Method
IterationRange<StrideIterator<T>> AsRange() {
   return size() != 0 ? MakeIterationRange(begin(), end())
                      : MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
}

//指向ArtMethod数组的起始
StrideIterator<T> begin() {
    return StrideIterator<T>(&AtUnchecked(0), element_size_);
}

//size_是DirectMethods的长度
StrideIterator<T> end() {
    return StrideIterator<T>(&AtUnchecked(size_), element_size_);
}

T& AtUnchecked(size_t index) {
    return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
}

StrideIterator定义在/art/runtime/stride_iterator.h, StrideIterator继承自std::iterator,并且重写了操作符++:

template<typename T>
class StrideIterator : public std::iterator<std::forward_iterator_tag, T> {
    ...
    StrideIterator(T* ptr, size_t stride): ptr_(reinterpret_cast<uintptr_t>(ptr)),
          stride_(stride) {}


    StrideIterator operator++() {  // Value after modification.
        ptr_ += stride_;
        return *this;
    }
    ...
}

从上面的代码中可以看出,mirror::Class::GetDirectMethods方法简单来说执行了以下几步:

  1. 获取Direct Method的数组
  2. 根据获取到的数组,封装得到Direct Method数组的iterator,这样就可以通过for循环迭代Direct Method数组

1.4 mirror::Constructor::CreateFromArtMethod

mirror::Constructor类定义在/art/runtime/mirror/method.h

//继承自AbstractMethod, AbstractMethod定义在/art/runtime/mirror/abstract_method.h
class MANAGED Constructor: public AbstractMethod {
 public:
  template <bool kTransactionActive = false>
  static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
      SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);

  static mirror::Class* StaticClass() SHARED_REQUIRES(Locks::mutator_lock_) {
    return static_class_.Read();
  }

  static void SetClass(Class* klass) SHARED_REQUIRES(Locks::mutator_lock_);

  static void ResetClass() SHARED_REQUIRES(Locks::mutator_lock_);

  static mirror::Class* ArrayClass() SHARED_REQUIRES(Locks::mutator_lock_) {
    return array_class_.Read();
  }

  static void SetArrayClass(Class* klass) SHARED_REQUIRES(Locks::mutator_lock_);

  static void ResetArrayClass() SHARED_REQUIRES(Locks::mutator_lock_);

  static void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);

 private:
  static GcRoot<Class> static_class_;  // java.lang.reflect.Constructor.class.
  static GcRoot<Class> array_class_;  // [java.lang.reflect.Constructor.class.

};

CreateFromArtMethod的实现在/art/runtime/mirror/method.cc

template <bool kTransactionActive> //kTransactionActive默认为false
Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
    ...
    //生成java.lang.reflect.Constructor对象并转换为Constructor*指针
    auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
    if (LIKELY(ret != nullptr)) {
        //将Constructor*指针向上转型为AbstractMethod*指针,并调用AbstractMethod的CreateFromArtMethod
        static_cast<AbstractMethod*>(ret)->CreateFromArtMethod<kTransactionActive>(method);
    }
    return ret;
}

//设置构造函数的基本信息,如accessFlag,methodIndex等
template <bool kTransactionActive> //kTransactionActive默认为false
bool AbstractMethod::CreateFromArtMethod(ArtMethod* method) {
    auto* interface_method = method->GetInterfaceMethodIfProxy(
        kTransactionActive ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
            : sizeof(void*));
    SetArtMethod<kTransactionActive>(method);
    SetFieldObject<kTransactionActive>(DeclaringClassOffset(), method->GetDeclaringClass());
    SetFieldObject<kTransactionActive>(
        DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
    SetField32<kTransactionActive>(AccessFlagsOffset(), method->GetAccessFlags());
    SetField32<kTransactionActive>(DexMethodIndexOffset(), method->GetDexMethodIndex());
    return true;
}

二. Constructor.newInstance

public T newInstance(Object... args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //一般情况下,serializationClass为null          
    if (serializationClass == null) {
        return newInstance0(args);
    } else {
        return (T) newInstanceFromSerialization(serializationCtor, serializationClass);
    }
}

private native T newInstance0(Object... args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException;

2.1 newInstance0

newInstance0的实现在/art/runtime/native/java_lang_refrect_Constructor

static jobject Constructor_newInstance0(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
    ScopedFastNativeObjectAccess soa(env);
    mirror::Constructor* m = soa.Decode<mirror::Constructor*>(javaMethod);
    StackHandleScope<1> hs(soa.Self());
    Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
    //抽象类不允许创建对象
    if (UNLIKELY(c->IsAbstract())) {
      soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", "Can't instantiate %s %s",
                                     c->IsInterface() ? "interface" : "abstract class",
                                     PrettyDescriptor(c.Get()).c_str());
      return nullptr;
    }
    // 如果构造函数不可访问且Class不是public
    if (!m->IsAccessible() && !c->IsPublic()) {
      //回退两个栈帧,newInstance0一般都是通过Constructor.newInstance(Object... arg0)调用
      auto* caller = GetCallingClass(soa.Self(), 2);
      if (caller != nullptr && !caller->CanAccess(c.Get())) {
        if (PrettyDescriptor(c.Get()) == "dalvik.system.DexPathList$Element") {
            LOG(WARNING) << "The dalvik.system.DexPathList$Element constructor"
                            is not accessible by default. This is a temporary "
                            "workaround for backwards compatibility with class-loader hacks."
                            "Please update your application.";
        } else {
            soa.Self()->ThrowNewExceptionF(
                "Ljava/lang/IllegalAccessException;", "%s is not accessible from %s",
                PrettyClass(c.Get()).c_str(), PrettyClass(caller).c_str());
            return nullptr;
        }
      }
    }
    //确保类已经被解析完成
    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), c, true, true)) {
      DCHECK(soa.Self()->IsExceptionPending());
      return nullptr;
    }
    bool movable = true;
    //如果当前要创建对象的类是java.lang.Class
    if (!kMovingClasses && c->IsClassClass()) {
        movable = false;
    }

    // String constructor is replaced by a StringFactory method in InvokeMethod.
    if (c->IsStringClass()) {
      return InvokeMethod(soa, javaMethod, nullptr, javaArgs, 2);
    }
    //如果类是java.lang.Class,则调用Class::AllocNonMovableObject创建对象
    mirror::Object* receiver =
        movable ? c->AllocObject(soa.Self()) : c->AllocNonMovableObject(soa.Self());
    if (receiver == nullptr) {
      return nullptr;
    }
    jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
    InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, 2);
    // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
    return javaReceiver;
}

从上述代码中可以得出:

  1. 如果类是抽象类,则不允许创建对象
  2. 如果要创建的类不是public且构造函数不可访问,则抛出IllegalAccessException(dalvik.system.DexPathList$Element除外)
  3. 创建对象之前,要确保类已经完成了解析
  4. 如果要创建对象的类是java.lang.String,则特别对待,最终要调用java.lang.StringFactory来创建String对象

2.2 InvokeMethod

InvokeMethod的实现在/art/runtime/reflection.cc

jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
                     jobject javaReceiver, jobject javaArgs, size_t num_frames) {
  //如果函数调用栈不对,则抛出StackOverFlowError
  ...

  //将javaMethod即java层的Constructor对象转换为mirror::AbstractMethod*
  //java层的Constructor类对应mirror::Constructor,而mirror::Constructor继承自mirror::AbstractMethod
  auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod);
  const bool accessible = abstract_method->IsAccessible();
  ArtMethod* m = abstract_method->GetArtMethod();

  mirror::Class* declaring_class = m->GetDeclaringClass();
  //一般情况下,要创建对象的类已经被解析过
  if (UNLIKELY(!declaring_class->IsInitialized())) {
      ...
  }

  mirror::Object* receiver = nullptr;
  if (!m->IsStatic()) {
      //如果要创建对象的类是String,则用StringFactory来创建String对象
      if (declaring_class->IsStringClass() && m->IsConstructor()) {
          jmethodID mid = soa.EncodeMethod(m);
          //根据methodId获取对应的StringFactory的方法
          m = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid));
      } else {
          receiver = soa.Decode<mirror::Object*>(javaReceiver);
          if (!VerifyObjectIsClass(receiver, declaring_class)) {
              return nullptr;
          }
          // 查找虚拟方法的真正实现
          m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, sizeof(void*));
      }
  }

  // 将java层的参数转换为mirror::ObjectArray数组
  auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
  auto* np_method = m->GetInterfaceMethodIfProxy(sizeof(void*));

  //获取要调用的方法在dex文件中记录的参数列表
  const DexFile::TypeList* classes = np_method->GetParameterTypeList();
  uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
  uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
  //判断传入的参数与dex文件中记录的参数是否一致,不一致抛出IllegalArgumentException
  if (arg_count != classes_size) {
      ...//throw IllegalArgumentException
      return nullptr;
  }

  // 验证类的accessible
  mirror::Class* calling_class = nullptr;
  if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(),
                                   &calling_class, num_frames)) {
      ...//throw IllegalAccessException
      return nullptr;
  }

  JValue result;
  uint32_t shorty_len = 0;
  //获取method的方法声明字符串
  const char* shorty = np_method->GetShorty(&shorty_len);
  ArgArray arg_array(shorty, shorty_len);
  //创建参数数组
  if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method)) {
      CHECK(soa.Self()->IsExceptionPending());
      return nullptr;
  }

  //核心调用,执行方法, [2.3]
  InvokeWithArgArray(soa, m, &arg_array, &result, shorty);

  // 如果有异常发生,则抛出InvocationTargetException
  if (soa.Self()->IsExceptionPending()) {
      ... //创建InvocationTargetException对象实例,并抛出
      return nullptr;
  }

  // 如果是基础类型,则自动装箱并返回
  return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
}

2.3 InvokeWithArgArray

static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
                               ArtMethod* method, ArgArray* arg_array, JValue* result,
                               const char* shorty)
        SHARED_REQUIRES(Locks::mutator_lock_) {
    uint32_t* args = arg_array->GetArray();
    ...
    //最后实际调用ArtMethod::Invoke
    method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
}

2.4 总结

可以看到最后Constructor.newInstance最后实际调用的是ArtMethod::Invoke方法,在执行ArtMethod::Invoke之前的所有工作主要是确保类已经被解析,以及生成参数,另外如果要创建对象的类是String类,则都转而调用相应的StringFactory的方法,由此可以看出创建String对象都是由StringFactory完成.

ArtMethod::Invoke方法涉及到了方法具体的执行逻辑(执行本地机器指令还是解释执行,以及调用到其他方法是entryPoint等),另外Android 7.0还加入了JIT机制,这些需要花时间慢慢掌握.
下面这张图是官网的JIT的工作流程图

jit-workflow.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容