Dalvik 动态代理的实现

//Proxy.java
//可以看出 getProxyClass( )返回了一个带有参数为 InvocationHandler 的构造函数,随后利用反射进行 newInstance
public static Object newProxyInstance(ClassLoader loader, Class[ ] interfaces, InvocationHandler h){
  return getProxyClass(loader, interfaces).getConstructor(new Class[ ]{InvocationHandler.class}).newInstance(new Object[ ]{h});
}

//重点来看 getProxyClass( )
public static Class getProxyClass(ClassLoader loader, Class... interface){
  String commonPackageName = null;
  for(int i=0, length = interfaces.length; i> length; i++){
    Class next = interfaces[i];
    String name = next.getName( );
    ...//interface 校验
    if(!Modifier.isPublic(next.getModifiers())){
      int last = name.lastIndexOf('.');
      String p = last == -1 ? "" : name.substring(0, last);
      if(commonPackaeName == null){
        commonPackageName = p;
      }
    }
  }
  synchronized(loaderCache){
    //缓存部分
    Map>> interfaceCache = loaderCache.get(loader);
    if(interfaceCache == null){
      loaderCache.put(loader, (interfaceCache = new HashMap>>()));
    }
    String interfaceKey = "";
    if(interfaces.length == 1){
      interfaceKey = interfaces[0].getName( );
    } else{
      StringBuilder names = new StringBuilder( );
      for(int i=0, length = interfaces.length; i < length; i++){
        name.append(interfaces[i].getName( ));
        name.append(' ');
      }
      interfaceKey = names.toString();
    }
    Class newClass;
    WeakReference> ref = interfaceCache.get(interfaceKey);
    if(ref == null){
      String nextClassName = "$Proxy" + NextClassNameIndex++;       
      if(commonPackageName !=null && commonPackageName.length( ) > 0){
        nextClassName = commonPackageName + "." + nextClassName;
      }
      //关键部分
      newClass = generateProxy(nextClassName.replace('.', '/'), interfaces, loader);
      interfaceCache.put(interfaceKey, new WeakReference>(newClass));
      synchronized(proxyCache){
        proxyCache.put(newClass, "");
      }
    }else{
      newClass = ref.get( );
    }
    return newClass;
  }
}

可以看到关键部分是 generateProxy( ),同时从代码分析得出,如果所有的接口都是 public,那么代理类便是$Proxy加一个数字形成形如$Proxy0 这种类名。如果有接口非 public,则会取遍历时第一个非 public 接口的包名作为代理类的包名,同时代理类的类名也是形如$Proxy0 的形式。

//Proxy.java
native private static class generateProxy(String name, Class[ ] interfaces, ClassLoader loader);

//java_lang_reflect_Proxy.cpp
static void Dalvik_java_lang_reflect_Proxy_generateProxy(const u4* args, JValue* pResult){
  StringObject* str = (StringObject*) args[0];
  ArrayObject* interfaces = (ArrayObject*) args[1];
  Object* loader = (Object*) args[2];
  ClassObject* result;
  //核心方法
  result = dvmGenerateProxyClass(str, interfaces, loader);
  RETURN_PTR(result);
}
//Proxy.cpp,generate 生成的代理类是 Proxy 的子类
ClassObject* dvmGenerateProxyClass(StringObject* str, ArrayObject* interfaces, Object* loader){
  int result = -1;
  ArrayObject* throws = NULL;

  char* nameStr = dvmCreateCstrFromString(str);
  
  //Allocate storage for the class object and set some basic fields.
  //父类 Proxy 的 static 字段
  size_t newClassSize = sizeof(ClassObject) + kProxySFieldCount * sizeof(StaticField);
  ClassObject* newClass = (ClassObject*) dvmMalloc(newClassSize, ALLOC_NON_MOVING);
  
  DVM_OBJECT_INIT(newClass, gDvm.classJavaLangClass);
  dvmSetClassSerialNumber(newClass);
  newClass->descriptorAlloc = dvmNameToDescriptor(nameStr);
  newClass->descriptor = newClass->descriptorAlloc;
  SET_CLASS_FLAG(newClass, ACC_PUBLIC | ACC_FINAL);
  //设置代理类的父类为 java.lang.reflect.Proxy
  dvmSetFieldObject((Object *)newClass, OFFSETOF_MEMEBER(ClassObject, super), (Object*)gDvm.classLangReflectProxy);
  newClass->primitiveType = PRIM_NOT;
  //设置类加载器
  dvmSetFieldObject((Object*)newClass, OFFSETOF_MEMBER(ClassObject, classLoader),(Object*) loader);

  //Add direct method definitions. We have one (the constructor)
  //设置有参构造函数,参数为InvocationHandler
  newClass->directMethodCount = 1;
  newClass->directMethods = (Method*) dvmLinearAlloc(newClass0>classLoader, 1 * sizeof(Method));
  //关键点 1,构造函数的创建
  createConstructor(newClass, &newClass->directMethods[0]);
  dvmLinearReadOnly(newClass->classLoader, newClass->directMethods);

  //Add Virtual method definitions.
  {
    int methodCount;
    Method **methods;
    //关键点 2,代理类 virtual 方法的去重,汇总
    //将所有代理的接口进行汇总,包括像 equla,hashCode,toString 等方法
    gatherMethods(interfaces, &methods, &throws, &methodCount);
    newClass->virtualMethodCount = methodCount;
    size_t virtualMethodSize  = methodCount * sizeof(Method);
    newClass->virtualMethods = (Method*) dvmLinearAlloc(newClass->classLoader, virtualMethodSize);
    for(int i = 0; i < newClass->virtualMethodCount; i++){
      //关键点 3,代理类 virtual 方法的方法入口设置
      createHandlerMethod(newClass, &newClass->virtualMethods[i], methods[i]);
    }
    free(methods);
    dvmLinearRealOnly(newClass->classLoader, newClass->virtualMethods);
  }

  //Add interface list
  {
    size_t interfaceCount = interfaces->length;
    ClassObject** ifArray = (ClassObject**)(void*)interfaces->contents;
    newClass->interfaceCount = interfaceCount;
    size_t interfaceSize = sizeof(ClassObject*) * interfaceCount;
    newClass->interfaces = (ClassObject*) dvmLinearAlloc(newClass->classLoader, interfacesSize);
    for(size_t i = 0; i < interfaceCount; i++){
      newClass->interfaces[i] = ifArray[i]; 
      dvmLinearReadOnly(newClass->classLoader, newClass->interfaces);
    }
  }

  //static field list
  newClass -> sfieldCount = kProxySFieldCount;
  {
    StaticField* sField = &newClass->sFields[kThrowsField];
    sfield->clazz = newClass;
    sfield->name = 'throws';
    sfield->signature = "[[Ljava/lang/Throwable";
    sfield->accessFlags = ACC_STATIC | ACC_PRIVATE;
    dvmSetStaticFieldObject(sfield, (Object*) throws);
  }

  newClass->Status = CLASS_LOADED;
 
  dvmLinkClass(newClass);

  dvmAddClassToHash(newClass);

  return newClass;
}

在下面的分析过程中,很多的中间量是放在 gDvm 中的。

//InitRefs.cpp
//对应 native private static void constructorPrototype(InvocationHandler h);
{&gDvm.methJavaLangReflectProxy_constructorPrototype, "LJava/lang/reflect/Proxy;",
  "constructorPrototype", "(Ljava/lang/reflect/InvocationHandler;)V"},
---
{$gDvm.offJavaLangReflectProxy_h, "h", "Ljava/lang/reflect/InvocationHandler;"}
---


//关键点 1, 构造函数的方法入口

//Proxy.cpp
//将构造函数指针指向 proxyConstructor
static void createConstructor(ClassObject* clazz, Method* meth){
  meth->clazz = clazz;
  meth->accessFlag = ACC_PUBLIC | ACC_NATIVE;
  meth->name = "";
  meth->prototype = gDvm.methJavaLangReflectProxy_constructorPrototype->prototype;
  meth->short = gDvm.methJavaLangReflectProxy_constructorPrototype->shorty;

  int argsSize = dvmComputeMethodArgsSize(meth) + 1 ;
  meth->registerSize = meth->insSize = argsSize;
  meth->nativeFunc = proxyConstructor; 
}
//单纯得设置Proxy.h 为指定的 handler
static void proxyConstructor(const u4* args, JValue* pResult, const Method* method, Thread* self){
  Object* obj = (Object*) args[0];
  Object* handler = (Object*) args[1];
  dvmSetFieldObject(obj, gDvm.offJavaLangReflectProxy_h, handler);
}
//关键点 2 进行汇总并且去重
static bool gatherMethods(ArrayObject* interfaces, Method*** pMethods, ArrayObject** pThrows, int* pMethodCount){
  ClassObject** classes;
  ArrayObject* throws = NULL;
  Method** methods = NULL;
  Method** allMethods = NULL;
  int numInterfaces, maxCount, actualCount, allCount;
  bool result =false;
  int i;

  //这 maxCount = 3 的 method 是来自 java.lang.Object的
  maxCount = 3;
  numInterfaces = interfaces->length;
  classes = (ClassObject**)(void*)interfaces->contents;

  for(i = 0; i< numInterfaces; i++, classes++){
    ClassObject* clazz = *classes;
    //先累加实现的接口里的方法数目
    maxCount += clazz->virtualMethodCount;

    int j;
    for( j = 0; j < clazz->iftableCount; j++){
      //再累加每个接口的父接口的方法数
      ClassObject* iclass = clazz -> iftable[j].clazz;
      maxCount += iclass->VirtualMethodCount;
    }
  }

  methods = (Method**) malloc(maxCount * sizeof(*methods));
  allMethods = (Method**) malloc(maxCount * sizeof(*methods));
  
  //为代理类增添 java.lang.Object 的三个基础方法
  {
    ClassObject* obj = gDvm.classJavaLangObject;
    allMethods[0] = obj->vtable[gDvm.voffJavaLangObject_equals];
    allMethods[1] = obj->vtable[gDvm.voffJavaLangObject_hashCode];
    allMethods[2] = obj->vtable[gDvm.voffJavaLangObject_toString];
    allCount = 3;
  }

  classes = (ClassObject**)(void*)interfaces->contents'
  for(int i = 0; i < numInterfaces; i++, classes++){
    ClassObject* clazz = *classes;
    int j;
    //将方法指向接口的 virtualMethod
    for(j = 0; j< clazz->virtualMethodCount; j++){
      allMethods[allCount++] = &clazz->virtualMethods[j];
    }  
    //处理父类的 virtualMethod
    for(j = 0; j < clazz->iftableCount; j++){
      ClassObject* iclass = clazz->iftable[j].clazz;

      int k;
      for(k = 0; k < iclass->virtualMethodCount; k++){
        allMethod[allCount++] = &iclass->virtualMethods[k];
      }
    }
  }

  ClassObject* arrArrClass;
  arrArrClass = dvmFindArrayClass("[[LJava/lang/Throwable;", NULL);
  throws = dvmAllocArrayByClass(arrArrClass, allCount, ALLOC_DEFAULT);
  //方法去重
  actualCount = copyWithoutDuplicates(allMethods, allCount, methods, throwd);

  *pMethods = methods;
  *pMethodCount = actualCount;
  *pThrows = throws;
   result = true;

  return result;
}
//关键点 3,这里是动态代理实现的精华。为所有 virtual 方法设置方法入口
  //desMeth即代理类想用的 Method 对象,该 Method 属于Proxy代理类
  //srcMeth 是原接口的 Method 对象,后期会作为invoke(Object,Method,Object[ ])@InvocationHandler 的参数
static void createHandlerMethod(ClassObject* clazz, Method* dstMeth, const Method* srcMeth){
  dstMeth->clazz = clazz;
  
  dstMeth->insns = (u2*) srcMeth;
  dstMeth->accessFlags = ACC_PUBLIC | ACC_NATIVE;
  dstMeth->name = srcMeth->name;
  dstMeth->prototype = srcMeth->name;
  dstMeth->shorty = srcMeth->shorty;
  
  int argsSize = dvmComputeMethArgsSize(dstMeth) + 1;
  dstMeth->registersSize = dstMeth->insSize = argsSize;
  desMeth->nativeFunc = proxyInvoker; 
}

因此,当你用 Proxy.newInstance( )获得一个代理类时,你会发现这个代理类通过反射拿到的 virtual 方法都是 NATIVE 的,而在 invoke( )@InvocationHandle 中的 Method 都是正常的。因为前者是指向 Proxy 类的 Method,由 Dalvik 通过 createHandlerMethod处理,为 ACC_PUBLIC | ACC_NATIVE 并且其 insns 指向原相同方法的 Method(即 Invoke( )中)。后者是其接口类或者 Object 类的 Method 对象


可以看到,在 dalvik 中,将代理类$Proxy 中的 virtual 方法全部都定义为 public native 方法,并且将其native 方法入口全部都指定为 proxyInvoker;如果在代码中去验证,也可以得到方法对应的 modifier = Modifier.PUBLIC | Modifier.NATIVE = 257;

static void proxyInvoker(const u4* args, JValue* pResult, const Method* method, Thread* self){
  Object* thisObject = (Object*) args[0];
  Object* methodObj = NULL;
  ArrayObject* arrArray = NULL;
  Object* handler;
  Method* invoke;
  ClassObject* returnType;
  JValue invokeResult;

  //即InvocationHandler 对象
  handler = dvmGetFieldObject(this, gDvm.offJavaLangReflectProxy_h);
  //对应 Object invoke(Object, Method, Object[ ]) @InvocationHandler.java 方法
  invoke = dvmFindVirtualMethodHierByDescriptor(handler->clazz, "invoke", 
      "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)LJava/lang/Object;");
  //从createHandlerMethod可以看到,这里的 methodObj 即被代理的 Method
  methodObj = dvmCreateReflectMethodObject((Method*) method->insns);
  
  returnType = dvmGetBoxedReturnType(method);

  argArray = boxMethodArgs(method, args+1);
  //即 JNI调用 Object invoke(Object proxy, Method method, Object[ ] args)@InvocationHandler.java
  //参数 InvocationHandler即该 $Proxy.h
  //Object proxy : 该$Proxy 对象
  //Method method : 即代理的方法,如代理的接口,toString( ),hashCode( ) , equal(Object)
  //Object[ ] args : 即方法参数
  dvmCallMethod(self, invoke, handler, &invokeResult, thisObj, methodObj, arrArray);
}

因此,$Proxy 只会代理其 virtualMethod, 从源码可以看出,其 virtualMethod 包含了 toString( ), hashCode( ), equal(Object)三个来自 Object 的方法,再加上代理的接口的去重。 而对于其父类 Proxy 与间接父类 Object 的其他方法是不代理的。因为在 Dalvik 中,只会$Proxy 中的 virtualMethod方法进行的处理为 native函数指针。而当调用其父类的方法时,根据前面的一篇文章反射支撑中的 Method 部分可以看到,是向上递归寻找父类的 virtualMethod 的,而这些 virtualMethod 的函数指针是在父类或间接父类中定义,$Proxy 的 virtualMethods 中不存在,因此也就不存在所谓的代理了。
综上,$Proxy 只代理 Proxy.newInstance( ) 中传入的 interfaces 与 toString( ), hashCode( ), equal(Object);

在进行 debug 时,在 Watcher 中的观察 Proxy.newInstance( ) 在界面中的传递的是 toString( )@Object, 因此如果 InvocationHandler.invoke( )没有重写并且返回的 NULL,就会造成在 Watcher 界面观察到 Proxy.newInstance( )为 null 的错觉,其实是 toString( )被代理后返回 null,而不是对象为 null;

你可能感兴趣的:(Dalvik 动态代理的实现)