生成步骤
1. Proxy.newProxyInstance2. Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);3. (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()4. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName,interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);5. final byte[] classFile = gen.generateClassFile();
代码
IPerson.java
public interface IPerson { String stduy(String name);}
JDKProxy
package A002动态代理;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JDKProxy<T> { //需要代理的对象。这里我们使用Iperson来接收Tom对象 private T target; public void setTarget(T target) { this.target = target; } public T getProxy() { Object o = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法执行前"); //执行原有的方法 Object invoke = method.invoke(target, args); System.out.println("方法执行后"); return invoke; } }); return (T) o; }}
Tom
package A002动态代理;public class Tom implements IPerson { @Override public String stduy(String name) { System.out.println("执行原生方法"); return Tom.class.getName()+name; }}
Test
package A002动态代理;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Test { public static void main(String[] args) throws IOException { JDKProxy<IPerson> iPersonJDKProxy = new JDKProxy<>(); //需要被代理的对象 IPerson tom = new Tom(); iPersonJDKProxy.setTarget(tom); //获取代理对象,此时这个对象就不再是上面的tom了 IPerson proxy = iPersonJDKProxy.getProxy(); proxy.stduy("java"); // 代理类的字节码数组 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( "RProxy0", new Class[]{IPerson.class}); FileOutputStream fileOutputStream = new FileOutputStream("/Users/zhaojian/code/java/InterviewDemo/src/main/kotlin/A002动态代理/IPersonProxy.class"); fileOutputStream.write(proxyClassFile); fileOutputStream.flush(); fileOutputStream.close(); }}
ProxyGenerator
package A002动态代理;import java.io.*;import java.lang.reflect.Array;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.nio.file.Files;import java.nio.file.Path;import java.util.*;//import sun.security.action.GetBooleanAction;class ProxyGenerator { private static final int CLASSFILE_MAJOR_VERSION = 49; private static final int CLASSFILE_MINOR_VERSION = 0; private static final int CONSTANT_UTF8 = 1; private static final int CONSTANT_UNICODE = 2; private static final int CONSTANT_INTEGER = 3; private static final int CONSTANT_FLOAT = 4; private static final int CONSTANT_LONG = 5; private static final int CONSTANT_DOUBLE = 6; private static final int CONSTANT_CLASS = 7; private static final int CONSTANT_STRING = 8; private static final int CONSTANT_FIELD = 9; private static final int CONSTANT_METHOD = 10; private static final int CONSTANT_INTERFACEMETHOD = 11; private static final int CONSTANT_NAMEANDTYPE = 12; private static final int ACC_PUBLIC = 0x00000001; private static final int ACC_PRIVATE = 0x00000002; // private static final int ACC_PROTECTED = 0x00000004; private static final int ACC_STATIC = 0x00000008; private static final int ACC_FINAL = 0x00000010; // private static final int ACC_SYNCHRONIZED = 0x00000020;// private static final int ACC_VOLATILE = 0x00000040;// private static final int ACC_TRANSIENT = 0x00000080;// private static final int ACC_NATIVE = 0x00000100;// private static final int ACC_INTERFACE = 0x00000200;// private static final int ACC_ABSTRACT = 0x00000400; private static final int ACC_SUPER = 0x00000020;// private static final int ACC_STRICT = 0x00000800; // private static final int opc_nop = 0; private static final int opc_aconst_null = 1; // private static final int opc_iconst_m1 = 2; private static final int opc_iconst_0 = 3; // private static final int opc_iconst_1 = 4;// private static final int opc_iconst_2 = 5;// private static final int opc_iconst_3 = 6;// private static final int opc_iconst_4 = 7;// private static final int opc_iconst_5 = 8;// private static final int opc_lconst_0 = 9;// private static final int opc_lconst_1 = 10;// private static final int opc_fconst_0 = 11;// private static final int opc_fconst_1 = 12;// private static final int opc_fconst_2 = 13;// private static final int opc_dconst_0 = 14;// private static final int opc_dconst_1 = 15; private static final int opc_bipush = 16; private static final int opc_sipush = 17; private static final int opc_ldc = 18; private static final int opc_ldc_w = 19; // private static final int opc_ldc2_w = 20; private static final int opc_iload = 21; private static final int opc_lload = 22; private static final int opc_fload = 23; private static final int opc_dload = 24; private static final int opc_aload = 25; private static final int opc_iload_0 = 26; // private static final int opc_iload_1 = 27;// private static final int opc_iload_2 = 28;// private static final int opc_iload_3 = 29; private static final int opc_lload_0 = 30; // private static final int opc_lload_1 = 31;// private static final int opc_lload_2 = 32;// private static final int opc_lload_3 = 33; private static final int opc_fload_0 = 34; // private static final int opc_fload_1 = 35;// private static final int opc_fload_2 = 36;// private static final int opc_fload_3 = 37; private static final int opc_dload_0 = 38; // private static final int opc_dload_1 = 39;// private static final int opc_dload_2 = 40;// private static final int opc_dload_3 = 41; private static final int opc_aload_0 = 42; // private static final int opc_aload_1 = 43;// private static final int opc_aload_2 = 44;// private static final int opc_aload_3 = 45;// private static final int opc_iaload = 46;// private static final int opc_laload = 47;// private static final int opc_faload = 48;// private static final int opc_daload = 49;// private static final int opc_aaload = 50;// private static final int opc_baload = 51;// private static final int opc_caload = 52;// private static final int opc_saload = 53;// private static final int opc_istore = 54;// private static final int opc_lstore = 55;// private static final int opc_fstore = 56;// private static final int opc_dstore = 57; private static final int opc_astore = 58; // private static final int opc_istore_0 = 59;// private static final int opc_istore_1 = 60;// private static final int opc_istore_2 = 61;// private static final int opc_istore_3 = 62;// private static final int opc_lstore_0 = 63;// private static final int opc_lstore_1 = 64;// private static final int opc_lstore_2 = 65;// private static final int opc_lstore_3 = 66;// private static final int opc_fstore_0 = 67;// private static final int opc_fstore_1 = 68;// private static final int opc_fstore_2 = 69;// private static final int opc_fstore_3 = 70;// private static final int opc_dstore_0 = 71;// private static final int opc_dstore_1 = 72;// private static final int opc_dstore_2 = 73;// private static final int opc_dstore_3 = 74; private static final int opc_astore_0 = 75; // private static final int opc_astore_1 = 76;// private static final int opc_astore_2 = 77;// private static final int opc_astore_3 = 78;// private static final int opc_iastore = 79;// private static final int opc_lastore = 80;// private static final int opc_fastore = 81;// private static final int opc_dastore = 82; private static final int opc_aastore = 83; // private static final int opc_bastore = 84;// private static final int opc_castore = 85;// private static final int opc_sastore = 86; private static final int opc_pop = 87; // private static final int opc_pop2 = 88; private static final int opc_dup = 89; // private static final int opc_dup_x1 = 90;// private static final int opc_dup_x2 = 91;// private static final int opc_dup2 = 92;// private static final int opc_dup2_x1 = 93;// private static final int opc_dup2_x2 = 94;// private static final int opc_swap = 95;// private static final int opc_iadd = 96;// private static final int opc_ladd = 97;// private static final int opc_fadd = 98;// private static final int opc_dadd = 99;// private static final int opc_isub = 100;// private static final int opc_lsub = 101;// private static final int opc_fsub = 102;// private static final int opc_dsub = 103;// private static final int opc_imul = 104;// private static final int opc_lmul = 105;// private static final int opc_fmul = 106;// private static final int opc_dmul = 107;// private static final int opc_idiv = 108;// private static final int opc_ldiv = 109;// private static final int opc_fdiv = 110;// private static final int opc_ddiv = 111;// private static final int opc_irem = 112;// private static final int opc_lrem = 113;// private static final int opc_frem = 114;// private static final int opc_drem = 115;// private static final int opc_ineg = 116;// private static final int opc_lneg = 117;// private static final int opc_fneg = 118;// private static final int opc_dneg = 119;// private static final int opc_ishl = 120;// private static final int opc_lshl = 121;// private static final int opc_ishr = 122;// private static final int opc_lshr = 123;// private static final int opc_iushr = 124;// private static final int opc_lushr = 125;// private static final int opc_iand = 126;// private static final int opc_land = 127;// private static final int opc_ior = 128;// private static final int opc_lor = 129;// private static final int opc_ixor = 130;// private static final int opc_lxor = 131;// private static final int opc_iinc = 132;// private static final int opc_i2l = 133;// private static final int opc_i2f = 134;// private static final int opc_i2d = 135;// private static final int opc_l2i = 136;// private static final int opc_l2f = 137;// private static final int opc_l2d = 138;// private static final int opc_f2i = 139;// private static final int opc_f2l = 140;// private static final int opc_f2d = 141;// private static final int opc_d2i = 142;// private static final int opc_d2l = 143;// private static final int opc_d2f = 144;// private static final int opc_i2b = 145;// private static final int opc_i2c = 146;// private static final int opc_i2s = 147;// private static final int opc_lcmp = 148;// private static final int opc_fcmpl = 149;// private static final int opc_fcmpg = 150;// private static final int opc_dcmpl = 151;// private static final int opc_dcmpg = 152;// private static final int opc_ifeq = 153;// private static final int opc_ifne = 154;// private static final int opc_iflt = 155;// private static final int opc_ifge = 156;// private static final int opc_ifgt = 157;// private static final int opc_ifle = 158;// private static final int opc_if_icmpeq = 159;// private static final int opc_if_icmpne = 160;// private static final int opc_if_icmplt = 161;// private static final int opc_if_icmpge = 162;// private static final int opc_if_icmpgt = 163;// private static final int opc_if_icmple = 164;// private static final int opc_if_acmpeq = 165;// private static final int opc_if_acmpne = 166;// private static final int opc_goto = 167;// private static final int opc_jsr = 168;// private static final int opc_ret = 169;// private static final int opc_tableswitch = 170;// private static final int opc_lookupswitch = 171; private static final int opc_ireturn = 172; private static final int opc_lreturn = 173; private static final int opc_freturn = 174; private static final int opc_dreturn = 175; private static final int opc_areturn = 176; private static final int opc_return = 177; private static final int opc_getstatic = 178; private static final int opc_putstatic = 179; private static final int opc_getfield = 180; // private static final int opc_putfield = 181; private static final int opc_invokevirtual = 182; private static final int opc_invokespecial = 183; private static final int opc_invokestatic = 184; private static final int opc_invokeinterface = 185; private static final int opc_new = 187; // private static final int opc_newarray = 188; private static final int opc_anewarray = 189; // private static final int opc_arraylength = 190; private static final int opc_athrow = 191; private static final int opc_checkcast = 192; // private static final int opc_instanceof = 193;// private static final int opc_monitorenter = 194;// private static final int opc_monitorexit = 195; private static final int opc_wide = 196;// private static final int opc_multianewarray = 197;// private static final int opc_ifnull = 198;// private static final int opc_ifnonnull = 199;// private static final int opc_goto_w = 200;// private static final int opc_jsr_w = 201; // end of constants copied from sun.tools.java.RuntimeConstants private static final String superclassName = "java/lang/reflect/Proxy"; private static final String handlerFieldName = "h"; private static final boolean saveGeneratedFiles = true; //java.security.AccessController.doPrivileged(new GetBooleanAction("jdk.proxy.ProxyGenerator.saveGeneratedFiles")).booleanValue(); private static final Method hashCodeMethod; private static final Method equalsMethod; private static final Method toStringMethod; static { try { hashCodeMethod = Object.class.getMethod("hashCode"); equalsMethod = Object.class.getMethod("equals", Object.class); toStringMethod = Object.class.getMethod("toString"); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } private final String className; private final Class<?>[] interfaces; private final int accessFlags; private final ConstantPool cp = new ConstantPool(); private final List<FieldInfo> fields = new ArrayList<>(); private final List<MethodInfo> methods = new ArrayList<>(); private final Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>(); private int proxyMethodCount = 0; private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) { this.className = className; this.interfaces = interfaces; this.accessFlags = accessFlags; } static byte[] generateProxyClass(final String name, Class<?>[] interfaces) { return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER)); } static byte[] generateProxyClass(final String name, Class<?>[] interfaces, int accessFlags) { ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags); final byte[] classFile = gen.generateClassFile(); if (saveGeneratedFiles) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() {try { int i = name.lastIndexOf('.'); Path path; if (i > 0) { Path dir = Path.of(name.substring(0, i).replace('.', File.separatorChar)); Files.createDirectories(dir); path = dir.resolve(name.substring(i + 1) + ".class"); } else { path = Path.of(name + ".class"); } Files.write(path, classFile); return null;} catch (IOException e) { throw new InternalError( "I/O exception saving generated file: " + e);} } }); } return classFile; } private static void checkReturnTypes(List<ProxyMethod> methods) { if (methods.size() < 2) { return; } LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>(); nextNewReturnType: for (ProxyMethod pm : methods) { Class<?> newReturnType = pm.returnType; if (newReturnType.isPrimitive()) { throw new IllegalArgumentException( "methods with same signature " + getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) + " but incompatible return types: " + newReturnType.getName() + " and others"); } boolean added = false; ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator(); while (liter.hasNext()) { Class<?> uncoveredReturnType = liter.next(); if (newReturnType.isAssignableFrom(uncoveredReturnType)) { assert !added; continue nextNewReturnType; } if (uncoveredReturnType.isAssignableFrom(newReturnType)) { // (we can assume that each return type is unique) if (!added) { liter.set(newReturnType); added = true; } else { liter.remove(); } } } if (!added) { uncoveredReturnTypes.add(newReturnType); } } if (uncoveredReturnTypes.size() > 1) { ProxyMethod pm = methods.get(0); throw new IllegalArgumentException( "methods with same signature " +getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +" but incompatible return types: " + uncoveredReturnTypes); } } private static String dotToSlash(String name) { return name.replace('.', '/'); } private static String getMethodDescriptor(Class<?>[] parameterTypes, Class<?> returnType) { return getParameterDescriptors(parameterTypes) + ((returnType == void.class) ? "V" : getFieldType(returnType)); } private static String getParameterDescriptors(Class<?>[] parameterTypes) { StringBuilder desc = new StringBuilder("("); for (int i = 0; i < parameterTypes.length; i++) { desc.append(getFieldType(parameterTypes[i])); } desc.append(')'); return desc.toString(); } private static String getFieldType(Class<?> type) { if (type.isPrimitive()) { return PrimitiveTypeInfo.get(type).baseTypeString; } else if (type.isArray()) { return type.getName().replace('.', '/'); } else { return "L" + dotToSlash(type.getName()) + ";"; } } private static String getFriendlyMethodSignature(String name, Class<?>[] parameterTypes) { StringBuilder sig = new StringBuilder(name); sig.append('('); for (int i = 0; i < parameterTypes.length; i++) { if (i > 0) { sig.append(','); } Class<?> parameterType = parameterTypes[i]; int dimensions = 0; while (parameterType.isArray()) { parameterType = parameterType.getComponentType(); dimensions++; } sig.append(parameterType.getName()); while (dimensions-- > 0) { sig.append("[]"); } } sig.append(')'); return sig.toString(); } private static int getWordsPerType(Class<?> type) { if (type == long.class || type == double.class) { return 2; } else { return 1; } } private static void collectCompatibleTypes(Class<?>[] from, Class<?>[] with, List<Class<?>> list) { for (Class<?> fc : from) { if (!list.contains(fc)) { for (Class<?> wc : with) { if (wc.isAssignableFrom(fc)) { list.add(fc); break; } } } } } private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) { List<Class<?>> uniqueList = new ArrayList<>(); // unique exceptions to catch uniqueList.add(Error.class); // always catch/rethrow these uniqueList.add(RuntimeException.class); nextException: for (Class<?> ex : exceptions) { if (ex.isAssignableFrom(Throwable.class)) { uniqueList.clear(); break; } else if (!Throwable.class.isAssignableFrom(ex)) { continue; } for (int j = 0; j < uniqueList.size(); ) { Class<?> ex2 = uniqueList.get(j); if (ex2.isAssignableFrom(ex)) { continue nextException; } else if (ex.isAssignableFrom(ex2)) { uniqueList.remove(j); } else { j++; // else continue comparing. } } // This exception is unique (so far): add it to the list to catch. uniqueList.add(ex); } return uniqueList; } private byte[] generateClassFile() { addProxyMethod(hashCodeMethod, Object.class); addProxyMethod(equalsMethod, Object.class); addProxyMethod(toStringMethod, Object.class); for (Class<?> intf : interfaces) { for (Method m : intf.getMethods()) { if (!Modifier.isStatic(m.getModifiers())) { addProxyMethod(m, intf); } } } for (List<ProxyMethod> sigmethods : proxyMethods.values()) { checkReturnTypes(sigmethods); } try { methods.add(generateConstructor()); for (List<ProxyMethod> sigmethods : proxyMethods.values()) { for (ProxyMethod pm : sigmethods) { // add static field for method's Method object fields.add(new FieldInfo(pm.methodFieldName,"Ljava/lang/reflect/Method;",ACC_PRIVATE | ACC_STATIC)); // generate code for proxy method and add it methods.add(pm.generateMethod()); } } methods.add(generateStaticInitializer()); } catch (IOException e) { throw new InternalError("unexpected I/O Exception", e); } if (methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } if (fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } cp.getClass(dotToSlash(className)); cp.getClass(superclassName); for (Class<?> intf : interfaces) { cp.getClass(dotToSlash(intf.getName())); } cp.setReadOnly(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); try { // u4 magic; dout.writeInt(0xCAFEBABE); // u2 minor_version; dout.writeShort(CLASSFILE_MINOR_VERSION); // u2 major_version; dout.writeShort(CLASSFILE_MAJOR_VERSION); cp.write(dout); // (write constant pool) // u2 access_flags; dout.writeShort(accessFlags); // u2 this_class; dout.writeShort(cp.getClass(dotToSlash(className))); // u2 super_class; dout.writeShort(cp.getClass(superclassName)); // u2 interfaces_count; dout.writeShort(interfaces.length); // u2 interfaces[interfaces_count]; for (Class<?> intf : interfaces) { dout.writeShort(cp.getClass( dotToSlash(intf.getName()))); } // u2 fields_count; dout.writeShort(fields.size()); // field_info fields[fields_count]; for (FieldInfo f : fields) { f.write(dout); } // u2 methods_count; dout.writeShort(methods.size()); // method_info methods[methods_count]; for (MethodInfo m : methods) { m.write(dout); } // u2 attributes_count; dout.writeShort(0); // (no ClassFile attributes for proxy classes) } catch (IOException e) { throw new InternalError("unexpected I/O Exception", e); } return bout.toByteArray(); } private void addProxyMethod(Method m, Class<?> fromClass) { String name = m.getName(); Class<?>[] parameterTypes = m.getParameterTypes(); Class<?> returnType = m.getReturnType(); Class<?>[] exceptionTypes = m.getExceptionTypes(); String sig = name + getParameterDescriptors(parameterTypes); List<ProxyMethod> sigmethods = proxyMethods.get(sig); if (sigmethods != null) { for (ProxyMethod pm : sigmethods) { if (returnType == pm.returnType) { List<Class<?>> legalExceptions = new ArrayList<>(); collectCompatibleTypes(exceptionTypes, pm.exceptionTypes, legalExceptions); collectCompatibleTypes(pm.exceptionTypes, exceptionTypes, legalExceptions); pm.exceptionTypes = new Class<?>[legalExceptions.size()]; pm.exceptionTypes =legalExceptions.toArray(pm.exceptionTypes); return; } } } else { sigmethods = new ArrayList<>(3); proxyMethods.put(sig, sigmethods); } sigmethods.add(new ProxyMethod(name, parameterTypes, returnType, exceptionTypes, fromClass)); } private MethodInfo generateConstructor() throws IOException { MethodInfo minfo = new MethodInfo( "" , "(Ljava/lang/reflect/InvocationHandler;)V", ACC_PUBLIC); DataOutputStream out = new DataOutputStream(minfo.code); code_aload(0, out); code_aload(1, out); out.writeByte(opc_invokespecial); out.writeShort(cp.getMethodRef( superclassName, "" , "(Ljava/lang/reflect/InvocationHandler;)V")); out.writeByte(opc_return); minfo.maxStack = 10; minfo.maxLocals = 2; minfo.declaredExceptions = new short[0]; return minfo; } private MethodInfo generateStaticInitializer() throws IOException { MethodInfo minfo = new MethodInfo( "" , "()V", ACC_STATIC); int localSlot0 = 1; short pc, tryBegin = 0, tryEnd; DataOutputStream out = new DataOutputStream(minfo.code); for (List<ProxyMethod> sigmethods : proxyMethods.values()) { for (ProxyMethod pm : sigmethods) { pm.codeFieldInitialization(out); } } out.writeByte(opc_return); tryEnd = pc = (short) minfo.code.size(); minfo.exceptionTable.add(new ExceptionTableEntry( tryBegin, tryEnd, pc, cp.getClass("java/lang/NoSuchMethodException"))); code_astore(localSlot0, out); out.writeByte(opc_new); out.writeShort(cp.getClass("java/lang/NoSuchMethodError")); out.writeByte(opc_dup); code_aload(localSlot0, out); out.writeByte(opc_invokevirtual); out.writeShort(cp.getMethodRef( "java/lang/Throwable", "getMessage", "()Ljava/lang/String;")); out.writeByte(opc_invokespecial); out.writeShort(cp.getMethodRef( "java/lang/NoSuchMethodError", "" , "(Ljava/lang/String;)V")); out.writeByte(opc_athrow); pc = (short) minfo.code.size(); minfo.exceptionTable.add(new ExceptionTableEntry( tryBegin, tryEnd, pc, cp.getClass("java/lang/ClassNotFoundException"))); code_astore(localSlot0, out); out.writeByte(opc_new); out.writeShort(cp.getClass("java/lang/NoClassDefFoundError")); out.writeByte(opc_dup); code_aload(localSlot0, out); out.writeByte(opc_invokevirtual); out.writeShort(cp.getMethodRef( "java/lang/Throwable", "getMessage", "()Ljava/lang/String;")); out.writeByte(opc_invokespecial); out.writeShort(cp.getMethodRef( "java/lang/NoClassDefFoundError", "" , "(Ljava/lang/String;)V")); out.writeByte(opc_athrow); if (minfo.code.size() > 65535) { throw new IllegalArgumentException("code size limit exceeded"); } minfo.maxStack = 10; minfo.maxLocals = (short) (localSlot0 + 1); minfo.declaredExceptions = new short[0]; return minfo; } private void code_iload(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out); }// private void code_istore(int lvar, DataOutputStream out)// throws IOException// {// codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);// }// private void code_lstore(int lvar, DataOutputStream out)// throws IOException// {// codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);// }// private void code_fstore(int lvar, DataOutputStream out)// throws IOException// {// codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);// }// private void code_dstore(int lvar, DataOutputStream out)// throws IOException// {// codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);// } private void code_lload(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out); } private void code_fload(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out); } private void code_dload(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out); } private void code_aload(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out); } private void code_astore(int lvar, DataOutputStream out) throws IOException { codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out); } private void codeLocalLoadStore(int lvar, int opcode, int opcode_0, DataOutputStream out) throws IOException { assert lvar >= 0 && lvar <= 0xFFFF; if (lvar <= 3) { out.writeByte(opcode_0 + lvar); } else if (lvar <= 0xFF) { out.writeByte(opcode); out.writeByte(lvar & 0xFF); } else { out.writeByte(opc_wide); out.writeByte(opcode); out.writeShort(lvar & 0xFFFF); } } private void code_ldc(int index, DataOutputStream out) throws IOException { assert index >= 0 && index <= 0xFFFF; if (index <= 0xFF) { out.writeByte(opc_ldc); out.writeByte(index & 0xFF); } else { out.writeByte(opc_ldc_w); out.writeShort(index & 0xFFFF); } } private void code_ipush(int value, DataOutputStream out) throws IOException { if (value >= -1 && value <= 5) { out.writeByte(opc_iconst_0 + value); } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { out.writeByte(opc_bipush); out.writeByte(value & 0xFF); } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { out.writeByte(opc_sipush); out.writeShort(value & 0xFFFF); } else { throw new AssertionError(); } } private void codeClassForName(Class<?> cl, DataOutputStream out) throws IOException { code_ldc(cp.getString(cl.getName()), out); out.writeByte(opc_invokestatic); out.writeShort(cp.getMethodRef( "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;")); } private static class ExceptionTableEntry { public short startPc; public short endPc; public short handlerPc; public short catchType; public ExceptionTableEntry(short startPc, short endPc, short handlerPc, short catchType) { this.startPc = startPc; this.endPc = endPc; this.handlerPc = handlerPc; this.catchType = catchType; } } private static class PrimitiveTypeInfo { private static final Map<Class<?>, PrimitiveTypeInfo> table = new HashMap<>(); static { add(byte.class, Byte.class); add(char.class, Character.class); add(double.class, Double.class); add(float.class, Float.class); add(int.class, Integer.class); add(long.class, Long.class); add(short.class, Short.class); add(boolean.class, Boolean.class); } public String baseTypeString; public String wrapperClassName; public String wrapperValueOfDesc; public String unwrapMethodName; public String unwrapMethodDesc; private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) { assert primitiveClass.isPrimitive(); baseTypeString = Array.newInstance(primitiveClass, 0).getClass().getName().substring(1); wrapperClassName = dotToSlash(wrapperClass.getName()); wrapperValueOfDesc = "(" + baseTypeString + ")L" + wrapperClassName + ";"; unwrapMethodName = primitiveClass.getName() + "Value"; unwrapMethodDesc = "()" + baseTypeString; } private static void add(Class<?> primitiveClass, Class<?> wrapperClass) { table.put(primitiveClass, new PrimitiveTypeInfo(primitiveClass, wrapperClass)); } public static PrimitiveTypeInfo get(Class<?> cl) { return table.get(cl); } } private static class ConstantPool { private final List<ConstantPool.Entry> pool = new ArrayList<>(32); private final Map<Object, Integer> map = new HashMap<>(16); private boolean readOnly = false; public short getUtf8(String s) { if (s == null) { throw new NullPointerException(); } return getValue(s); } public short getInteger(int i) { return getValue(i); } public short getFloat(float f) { return getValue(f); } public short getClass(String name) { short utf8Index = getUtf8(name); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_CLASS, utf8Index)); } public short getString(String s) { short utf8Index = getUtf8(s); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_STRING, utf8Index)); } public short getFieldRef(String className, String name, String descriptor) { short classIndex = getClass(className); short nameAndTypeIndex = getNameAndType(name, descriptor); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_FIELD, classIndex, nameAndTypeIndex)); } public short getMethodRef(String className, String name, String descriptor) { short classIndex = getClass(className); short nameAndTypeIndex = getNameAndType(name, descriptor); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_METHOD, classIndex, nameAndTypeIndex)); } public short getInterfaceMethodRef(String className, String name, String descriptor) { short classIndex = getClass(className); short nameAndTypeIndex = getNameAndType(name, descriptor); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex)); } public short getNameAndType(String name, String descriptor) { short nameIndex = getUtf8(name); short descriptorIndex = getUtf8(descriptor); return getIndirect(new ConstantPool.IndirectEntry( CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex)); } public void setReadOnly() { readOnly = true; } public void write(OutputStream out) throws IOException { DataOutputStream dataOut = new DataOutputStream(out); // constant_pool_count: number of entries plus one dataOut.writeShort(pool.size() + 1); for (ConstantPool.Entry e : pool) { e.write(dataOut); } } private short addEntry(ConstantPool.Entry entry) { pool.add(entry); if (pool.size() >= 65535) { throw new IllegalArgumentException( "constant pool size limit exceeded"); } return (short) pool.size(); } private short getValue(Object key) { Integer index = map.get(key); if (index != null) { return index.shortValue(); } else { if (readOnly) { throw new InternalError("late constant pool addition: " + key); } short i = addEntry(new ConstantPool.ValueEntry(key)); map.put(key, (int) i); return i; } } private short getIndirect(ConstantPool.IndirectEntry e) { Integer index = map.get(e); if (index != null) { return index.shortValue(); } else { if (readOnly) { throw new InternalError("late constant pool addition"); } short i = addEntry(e); map.put(e, (int) i); return i; } } private abstract static class Entry { public abstract void write(DataOutputStream out) throws IOException; } private static class ValueEntry extends ConstantPool.Entry { private final Object value; public ValueEntry(Object value) { this.value = value; } public void write(DataOutputStream out) throws IOException { if (value instanceof String) { out.writeByte(CONSTANT_UTF8); out.writeUTF((String) value); } else if (value instanceof Integer) { out.writeByte(CONSTANT_INTEGER); out.writeInt(((Integer) value).intValue()); } else if (value instanceof Float) { out.writeByte(CONSTANT_FLOAT); out.writeFloat(((Float) value).floatValue()); } else if (value instanceof Long) { out.writeByte(CONSTANT_LONG); out.writeLong(((Long) value).longValue()); } else if (value instanceof Double) { out.writeDouble(CONSTANT_DOUBLE); out.writeDouble(((Double) value).doubleValue()); } else { throw new InternalError("bogus value entry: " + value); } } } private static class IndirectEntry extends ConstantPool.Entry { private final int tag; private final short index0; private final short index1; public IndirectEntry(int tag, short index) { this.tag = tag; this.index0 = index; this.index1 = 0; } public IndirectEntry(int tag, short index0, short index1) { this.tag = tag; this.index0 = index0; this.index1 = index1; } public void write(DataOutputStream out) throws IOException { out.writeByte(tag); out.writeShort(index0); if (tag == CONSTANT_FIELD || tag == CONSTANT_METHOD || tag == CONSTANT_INTERFACEMETHOD || tag == CONSTANT_NAMEANDTYPE) { out.writeShort(index1); } } public int hashCode() { return tag + index0 + index1; } public boolean equals(Object obj) { if (obj instanceof ConstantPool.IndirectEntry) { ConstantPool.IndirectEntry other = (ConstantPool.IndirectEntry) obj; return tag == other.tag &&index0 == other.index0 && index1 == other.index1; } return false; } } } private class FieldInfo { public int accessFlags; public String name; public String descriptor; public FieldInfo(String name, String descriptor, int accessFlags) { this.name = name; this.descriptor = descriptor; this.accessFlags = accessFlags; cp.getUtf8(name); cp.getUtf8(descriptor); } public void write(DataOutputStream out) throws IOException { // u2 access_flags; out.writeShort(accessFlags); // u2 name_index; out.writeShort(cp.getUtf8(name)); // u2 descriptor_index; out.writeShort(cp.getUtf8(descriptor)); // u2 attributes_count; out.writeShort(0); // (no field_info attributes for proxy classes) } } private class MethodInfo { public int accessFlags; public String name; public String descriptor; public short maxStack; public short maxLocals; public ByteArrayOutputStream code = new ByteArrayOutputStream(); public List<ExceptionTableEntry> exceptionTable = new ArrayList<ExceptionTableEntry>(); public short[] declaredExceptions; public MethodInfo(String name, String descriptor, int accessFlags) { this.name = name; this.descriptor = descriptor; this.accessFlags = accessFlags; cp.getUtf8(name); cp.getUtf8(descriptor); cp.getUtf8("Code"); cp.getUtf8("Exceptions"); } public void write(DataOutputStream out) throws IOException { // u2 access_flags; out.writeShort(accessFlags); // u2 name_index; out.writeShort(cp.getUtf8(name)); // u2 descriptor_index; out.writeShort(cp.getUtf8(descriptor)); // u2 attributes_count; out.writeShort(2); // (two method_info attributes:) // Write "Code" attribute. See JVMS section 4.7.3. // u2 attribute_name_index; out.writeShort(cp.getUtf8("Code")); // u4 attribute_length; out.writeInt(12 + code.size() + 8 * exceptionTable.size()); // u2 max_stack; out.writeShort(maxStack); // u2 max_locals; out.writeShort(maxLocals); // u2 code_length; out.writeInt(code.size()); // u1 code[code_length]; code.writeTo(out); // u2 exception_table_length; out.writeShort(exceptionTable.size()); for (ExceptionTableEntry e : exceptionTable) { // u2 start_pc; out.writeShort(e.startPc); // u2 end_pc; out.writeShort(e.endPc); // u2 handler_pc; out.writeShort(e.handlerPc); // u2 catch_type; out.writeShort(e.catchType); } // u2 attributes_count; out.writeShort(0); // write "Exceptions" attribute. See JVMS section 4.7.4. // u2 attribute_name_index; out.writeShort(cp.getUtf8("Exceptions")); // u4 attributes_length; out.writeInt(2 + 2 * declaredExceptions.length); // u2 number_of_exceptions; out.writeShort(declaredExceptions.length); // u2 exception_index_table[number_of_exceptions]; for (short value : declaredExceptions) { out.writeShort(value); } } } private class ProxyMethod { public String methodName; public Class<?>[] parameterTypes; public Class<?> returnType; public Class<?>[] exceptionTypes; public Class<?> fromClass; public String methodFieldName; private ProxyMethod(String methodName, Class<?>[] parameterTypes,Class<?> returnType, Class<?>[] exceptionTypes,Class<?> fromClass) { this.methodName = methodName; this.parameterTypes = parameterTypes; this.returnType = returnType; this.exceptionTypes = exceptionTypes; this.fromClass = fromClass; this.methodFieldName = "m" + proxyMethodCount++; } private MethodInfo generateMethod() throws IOException { String desc = getMethodDescriptor(parameterTypes, returnType); MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL); int[] parameterSlot = new int[parameterTypes.length]; int nextSlot = 1; for (int i = 0; i < parameterSlot.length; i++) { parameterSlot[i] = nextSlot; nextSlot += getWordsPerType(parameterTypes[i]); } int localSlot0 = nextSlot; short pc, tryBegin = 0, tryEnd; DataOutputStream out = new DataOutputStream(minfo.code); code_aload(0, out); out.writeByte(opc_getfield); out.writeShort(cp.getFieldRef( superclassName, handlerFieldName, "Ljava/lang/reflect/InvocationHandler;")); code_aload(0, out); out.writeByte(opc_getstatic); out.writeShort(cp.getFieldRef( dotToSlash(className), methodFieldName, "Ljava/lang/reflect/Method;")); if (parameterTypes.length > 0) { code_ipush(parameterTypes.length, out); out.writeByte(opc_anewarray); out.writeShort(cp.getClass("java/lang/Object")); for (int i = 0; i < parameterTypes.length; i++) { out.writeByte(opc_dup); code_ipush(i, out); codeWrapArgument(parameterTypes[i], parameterSlot[i], out); out.writeByte(opc_aastore); } } else { out.writeByte(opc_aconst_null); } out.writeByte(opc_invokeinterface); out.writeShort(cp.getInterfaceMethodRef( "java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +"[Ljava/lang/Object;)Ljava/lang/Object;")); out.writeByte(4); out.writeByte(0); if (returnType == void.class) { out.writeByte(opc_pop); out.writeByte(opc_return); } else { codeUnwrapReturnValue(returnType, out); } tryEnd = pc = (short) minfo.code.size(); List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes); if (catchList.size() > 0) { for (Class<?> ex : catchList) { minfo.exceptionTable.add(new ExceptionTableEntry(tryBegin, tryEnd, pc,cp.getClass(dotToSlash(ex.getName())))); } out.writeByte(opc_athrow); pc = (short) minfo.code.size(); minfo.exceptionTable.add(new ExceptionTableEntry( tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable"))); code_astore(localSlot0, out); out.writeByte(opc_new); out.writeShort(cp.getClass( "java/lang/reflect/UndeclaredThrowableException")); out.writeByte(opc_dup); code_aload(localSlot0, out); out.writeByte(opc_invokespecial); out.writeShort(cp.getMethodRef( "java/lang/reflect/UndeclaredThrowableException", "" , "(Ljava/lang/Throwable;)V")); out.writeByte(opc_athrow); } if (minfo.code.size() > 65535) { throw new IllegalArgumentException("code size limit exceeded"); } minfo.maxStack = 10; minfo.maxLocals = (short) (localSlot0 + 1); minfo.declaredExceptions = new short[exceptionTypes.length]; for (int i = 0; i < exceptionTypes.length; i++) { minfo.declaredExceptions[i] = cp.getClass( dotToSlash(exceptionTypes[i].getName())); } return minfo; } private void codeWrapArgument(Class<?> type, int slot, DataOutputStream out) throws IOException { if (type.isPrimitive()) { PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type); if (type == int.class || type == boolean.class || type == byte.class || type == char.class || type == short.class) { code_iload(slot, out); } else if (type == long.class) { code_lload(slot, out); } else if (type == float.class) { code_fload(slot, out); } else if (type == double.class) { code_dload(slot, out); } else { throw new AssertionError(); } out.writeByte(opc_invokestatic); out.writeShort(cp.getMethodRef( prim.wrapperClassName, "valueOf", prim.wrapperValueOfDesc)); } else { code_aload(slot, out); } } private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out) throws IOException { if (type.isPrimitive()) { PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type); out.writeByte(opc_checkcast); out.writeShort(cp.getClass(prim.wrapperClassName)); out.writeByte(opc_invokevirtual); out.writeShort(cp.getMethodRef( prim.wrapperClassName, prim.unwrapMethodName, prim.unwrapMethodDesc)); if (type == int.class || type == boolean.class || type == byte.class || type == char.class || type == short.class) { out.writeByte(opc_ireturn); } else if (type == long.class) { out.writeByte(opc_lreturn); } else if (type == float.class) { out.writeByte(opc_freturn); } else if (type == double.class) { out.writeByte(opc_dreturn); } else { throw new AssertionError(); } } else { out.writeByte(opc_checkcast); out.writeShort(cp.getClass(dotToSlash(type.getName()))); out.writeByte(opc_areturn); } } private void codeFieldInitialization(DataOutputStream out) throws IOException { codeClassForName(fromClass, out); code_ldc(cp.getString(methodName), out); code_ipush(parameterTypes.length, out); out.writeByte(opc_anewarray); out.writeShort(cp.getClass("java/lang/Class")); for (int i = 0; i < parameterTypes.length; i++) { out.writeByte(opc_dup); code_ipush(i, out); if (parameterTypes[i].isPrimitive()) { PrimitiveTypeInfo prim =PrimitiveTypeInfo.get(parameterTypes[i]); out.writeByte(opc_getstatic); out.writeShort(cp.getFieldRef(prim.wrapperClassName, "TYPE", "Ljava/lang/Class;")); } else { codeClassForName(parameterTypes[i], out); } out.writeByte(opc_aastore); } out.writeByte(opc_invokevirtual); out.writeShort(cp.getMethodRef( "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)" +"Ljava/lang/reflect/Method;")); out.writeByte(opc_putstatic); out.writeShort(cp.getFieldRef( dotToSlash(className), methodFieldName, "Ljava/lang/reflect/Method;")); } }}
生成的字节码
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//import A002动态代理.IPerson;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class RProxy0 extends Proxy implements IPerson { private static Method m1; private static Method m3; private static Method m2; private static Method m0;//protected Proxy(InvocationHandler h) { // Objects.requireNonNull(h); // this.h = h; //} public RProxy0(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 stduy(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 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 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")); m3 = Class.forName("A002动态代理.IPerson").getMethod("stduy", Class.forName("java.lang.String")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }}
资料
jdk动态代理&cglb动态代理到底生成了啥(一)
动态代理类
动态代理
JAVA创建一个私有域_【package-private】包私有类的食用姿势
来源地址:https://blog.csdn.net/AdrianAndroid/article/details/132580269