一、 dubbo的SPI代理和Invoker的代理
入口:createAdaptiveExtensionClass -> CtClass.toClass
入口:Proxy getProx -> ClassGenerator.toClass -> CtClass.toClass
二、JDK动态代理效率比Cglib动态代理低的原因
JDK动态代理,方法调用的核心如下:
private static class JdkHandler implements InvocationHandler {
final Object delegate;
JdkHandler(Object delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object object, Method method, Object[] objects)
throws Throwable {
return method.invoke(delegate, objects);
}
}
该invoke方法的核心是使用method.invoke进行反射调用,方法调用并没有直接去类的方法表去搜索。
而Cglib动态代理,方法调用核心如下:
private static class CglibInterceptor implements MethodInterceptor {
final Object delegate;
CglibInterceptor(Object delegate) {
this.delegate = delegate;
}
@Override
public Object intercept(Object object, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
return methodProxy.invoke(delegate, objects);
}
}
该invoke方法的核心是使用MethodProxy.invoke进行调用,而非反射调用。methodProxy的调用为啥会快于反射调用呢。是因为cglib为被代理类
也生成了代理类,然后通过fastClass机制调用。性能可以比肩对象直接调用,稍微有些性能损失,但是要强于反射调用。
fastClass的invoke方法是抽象方法,无法在cglib的源码中找到实现类。为啥呢?因为fastClass是和业务类紧密关联的,cglib没法知道业务类有哪些,只能在运行的时候,通过init里面的helper()方法动态生成fastClass。这个fastClass运行期间,只生成一次,后面再获取可以直接从缓存中拿。而fastClass经过反编译,可以看到源码。
什么是fastClass机制呢?
参考文档:https://blog.csdn.net/yzb808/article/details/88641156
FastClass的实现逻辑,是生成增强类实现invoke方法,invoke方法中,用switch语义将被增强类的所有方法调用枚举出来。用户使用FastClass.invoke方法,传入方法签名和被调用实例,从而达到不使用反射就能实现不确定方法的调用。
FastClass是否真的能比反射调用速度快吗?
参考文档:https://blog.csdn.net/yzb808/article/details/88641156
测试代码如上面的文档中,暂时就不贴了。从测试结果上看,一千万次调用的总耗时,默认情况下,反射执行效率明显优于FastClass。反射操作的时间开销主要存在于获取被反射的方法信息上,默认情况下使用JNI访问器获得该信息。但高版本的JVM在执行反射时引入通胀概念,也即参数-Dsun.reflect.inflationThreshold(默认15)。当一段反射逻辑执行次数超过阈值后,会生成被反射类对应的字节码访问器(sun/reflect/GeneratedMethodAccessor和sun/reflect/DelegatingClassLoader),用于加快反射调用。测试代码中提高通胀阈值后发现反射的执行效率变得很差。
使用FastClass或反射生成字节码访问器都会构造新类占用perm区,网上看到一些oom的例子。但从执行效率方面考量,反射性能更好。
————————————————
学习了!
网友评论