private String sig(Class<?>[] params) { StringBuilder methodSig = new StringBuilder(); for (int i = 0; i < params.length; i++) { methodSig.append(sig(params[i])); } return methodSig.toString(); }
String runnableClassName = runnable(index, method); cw.visit(V1_4, ACC_FINAL + ACC_SUPER, runnableClassName, null, OBJECT_CLASS, new String[] { RUNNABLE }); fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "target", sig(interfaceName), null, null); fv.visitEnd(); fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "param"+i, sig(params[i]), null, null); fv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(" + sig(interfaceName)+sig(params)+")V", null, null); mv.visitFieldInsn(PUTFIELD, runnableClassName, "target", sig(interfaceName)); mv.visitFieldInsn(PUTFIELD, runnableClassName, "param"+i, sig(params[i])); mv.visitLocalVariable("this", sig(runnableClassName), null, start, end, 0); mv.visitLocalVariable("target", sig(interfaceName), null, start, end, 1); mv.visitLocalVariable("param"+i, sig(params[i]), null, start, end, 2+i); mv.visitLabel(start); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, runnableClassName, "target", sig(interfaceName)); mv.visitFieldInsn(GETFIELD, runnableClassName, "param"+i, sig(params[i])); mv.visitLocalVariable("this", sig(runnableClassName), null, start, end, 0); mv.visitMaxs(0, 0);
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "queue", sig(DISPATCH_QUEUE), null, null); fv.visitEnd(); fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, "target", sig(interfaceName), null, null); fv.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(" + sig(interfaceName) + sig(DISPATCH_QUEUE) + ")V", null, null); mv.visitFieldInsn(PUTFIELD, proxyName, "queue", sig(DISPATCH_QUEUE)); mv.visitFieldInsn(PUTFIELD, proxyName, "target", sig(interfaceName)); mv.visitLocalVariable("this", sig(proxyName), null, start, end, 0); mv.visitLocalVariable("target", sig(interfaceName), null, start, end, 1); mv.visitLocalVariable("queue", sig(DISPATCH_QUEUE), null, start, end, 2); mv.visitMaxs(2, 3); mv.visitLabel(start); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, proxyName, "queue", sig(DISPATCH_QUEUE)); mv.visitTypeInsn(NEW, runnable(index, methods[index])); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, proxyName, "target", sig(interfaceName)); mv.visitMethodInsn(INVOKESPECIAL, runnable(index, methods[index]), "<init>", "(" + sig(interfaceName) + sig(params) +")V"); mv.visitMethodInsn(INVOKEINTERFACE, DISPATCH_QUEUE, "execute", "(" + sig(RUNNABLE) + ")V"); Integer returnValue = defaultConstant(returnType);
@SuppressWarnings("unchecked") private static <T> Class<T> getProxyClass(ClassLoader loader, Class<T> interfaceClass) throws IllegalArgumentException { String proxyName = proxyName(interfaceClass); try { return (Class<T>) loader.loadClass(proxyName); } catch (ClassNotFoundException e) { Generator generator = new Generator(loader, interfaceClass); return generator.generate(); } }
private Class<T> generate() throws IllegalArgumentException { // Define all the runnable classes used for each method. Method[] methods = interfaceClass.getMethods(); for (int index = 0; index < methods.length; index++) { String name = runnable(index, methods[index]).replace('/', '.'); byte[] clazzBytes = dumpRunnable(index, methods[index]); defineClass(name, clazzBytes); } String name = proxyName.replace('/', '.'); byte[] clazzBytes = dumpProxy(methods); return defineClass(name, clazzBytes); }