//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;