JDK 动态代理
Demo
对于被代理的接口类,Proxy 会保证只有一个,但是它的实例会有多个,每个实例都会有对应的 InvocationHandler
Proxy 的 API
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
输出被代理的 Class 到文件:
Class<?> proxyClass = Proxy.getProxyClass(Invoker.class.getClassLoader(), Invoker.class);
Files.write(new File("ProxyClazz.class").toPath(), ProxyGenerator.generateProxyClass("ProxyClazz", proxyClass.getInterfaces()));
ProxyGenerator 会根据传入的接口,找到其对应的 Proxy 的实现类,由于 Proxy 保证的唯一性,所以只会存在一个
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.example.demo.dynamicproxy.Invoker;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class ProxyClazz extends Proxy implements Invoker {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public ProxyClazz(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String invoke(String var1) throws {
try {
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.example.demo.dynamicproxy.Invoker").getMethod("invoke", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
使用 Evaluate Expression,将动态代理类输出到文件:
Proxy 类中使用了 WeakCache 作为 Class 的缓存:
Key 和 Value 也分别使用了其内部类(工厂类)
而 ProxyClassFactory 中使用了 ProxyGenerator.generateProxyClass() 来创建代理类,ProxyGenerator 中是使用字节流的方式进行类的动态生成。
public class Proxy implements java.io.Serializable {
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
}
TODO
- 想办法把 Class 变成 byte[] 或者直接输出成文件(拦截 defineClass0?或者使用 javaagent)
- 不知道动态生成的 class 会不会被 javaagent 拦截
- byte[] -> Class 记笔记
CGLib
ClassLoadingMXBean、Enhancer
// 测试元空间 OOM
public static void main(String[] args) {
ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
while (true) {
// 设置增强类信息
Enhancer enhancer = new Enhancer();
// 被增强的类
enhancer.setSuperclass(Hello.class);
enhancer.setCallbackTypes(new Class[]{Dispatcher.class, MethodInterceptor.class});
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
return 1;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
});
Class clazz = enhancer.createClass();
System.out.println(clazz.getName());
//显示数量信息(共加载过的类型数目,当前还有效的类型数目,已经被卸载的类型数目)
System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
System.out.println("active: " + loadingBean.getLoadedClassCount());
System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
}
}