2009 lines · 77.6 KB · Java
RawDownload
/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.misc; import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.lang.reflect.Array;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.ListIterator;import java.util.Map;import sun.security.action.GetBooleanAction; /** * ProxyGenerator contains the code to generate a dynamic proxy class * for the java.lang.reflect.Proxy API. * * The external interfaces to ProxyGenerator is the static * "generateProxyClass" method. * * @author      Peter Jones * @since       1.3 */public class ProxyGenerator {    /*     * In the comments below, "JVMS" refers to The Java Virtual Machine     * Specification Second Edition and "JLS" refers to the original     * version of The Java Language Specification, unless otherwise     * specified.     */     /* generate 1.5-era class file version */    private static final int CLASSFILE_MAJOR_VERSION = 49;    private static final int CLASSFILE_MINOR_VERSION = 0;     /*     * beginning of constants copied from     * sun.tools.java.RuntimeConstants (which no longer exists):     */     /* constant pool tags */    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;     /* access and modifier flags */    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;     /* opcodes *///  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     /** name of the superclass of proxy classes */    private final static String superclassName = "java/lang/reflect/Proxy";     /** name of field for storing a proxy instance's invocation handler */    private final static String handlerFieldName = "h";     /** debugging flag for saving generated class files */    private final static boolean saveGeneratedFiles =        java.security.AccessController.doPrivileged(            new GetBooleanAction(                "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();     /**     * Generate a proxy class given a name and a list of proxy interfaces.     */    public static byte[] generateProxyClass(final String name,                                            Class[] interfaces)    {        ProxyGenerator gen = new ProxyGenerator(name, interfaces);        final byte[] classFile = gen.generateClassFile();         if (saveGeneratedFiles) {            java.security.AccessController.doPrivileged(            new java.security.PrivilegedAction<Void>() {                public Void run() {                    try {                        FileOutputStream file =                            new FileOutputStream(dotToSlash(name) + ".class");                        file.write(classFile);                        file.close();                        return null;                    } catch (IOException e) {                        throw new InternalError(                            "I/O exception saving generated file: " + e);                    }                }            });        }         return classFile;    }     /* preloaded Method objects for methods in java.lang.Object */    private static Method hashCodeMethod;    private static Method equalsMethod;    private static Method toStringMethod;    static {        try {            hashCodeMethod = Object.class.getMethod("hashCode");            equalsMethod =                Object.class.getMethod("equals", new Class[] { Object.class });            toStringMethod = Object.class.getMethod("toString");        } catch (NoSuchMethodException e) {            throw new NoSuchMethodError(e.getMessage());        }    }     /** name of proxy class */    private String className;     /** proxy interfaces */    private Class[] interfaces;     /** constant pool of class being generated */    private ConstantPool cp = new ConstantPool();     /** FieldInfo struct for each field of generated class */    private List<FieldInfo> fields = new ArrayList<FieldInfo>();     /** MethodInfo struct for each method of generated class */    private List<MethodInfo> methods = new ArrayList<MethodInfo>();     /**     * maps method signature string to list of ProxyMethod objects for     * proxy methods with that signature     */    private Map<String, List<ProxyMethod>> proxyMethods =        new HashMap<String,List<ProxyMethod>>();     /** count of ProxyMethod objects added to proxyMethods */    private int proxyMethodCount = 0;     /**     * Construct a ProxyGenerator to generate a proxy class with the     * specified name and for the given interfaces.     *     * A ProxyGenerator object contains the state for the ongoing     * generation of a particular proxy class.     */    private ProxyGenerator(String className, Class[] interfaces) {        this.className = className;        this.interfaces = interfaces;    }     /**     * Generate a class file for the proxy class.  This method drives the     * class file generation process.     */    private byte[] generateClassFile() {         /* ============================================================         * Step 1: Assemble ProxyMethod objects for all methods to         * generate proxy dispatching code for.         */         /*         * Record that proxy methods are needed for the hashCode, equals,         * and toString methods of java.lang.Object.  This is done before         * the methods from the proxy interfaces so that the methods from         * java.lang.Object take precedence over duplicate methods in the         * proxy interfaces.         */        addProxyMethod(hashCodeMethod, Object.class);        addProxyMethod(equalsMethod, Object.class);        addProxyMethod(toStringMethod, Object.class);         /*         * Now record all of the methods from the proxy interfaces, giving         * earlier interfaces precedence over later ones with duplicate         * methods.         */        for (int i = 0; i < interfaces.length; i++) {            Method[] methods = interfaces[i].getMethods();            for (int j = 0; j < methods.length; j++) {                addProxyMethod(methods[j], interfaces[i]);            }        }         /*         * For each set of proxy methods with the same signature,         * verify that the methods' return types are compatible.         */        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {            checkReturnTypes(sigmethods);        }         /* ============================================================         * Step 2: Assemble FieldInfo and MethodInfo structs for all of         * fields and methods in the class we are generating.         */        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");        }         if (methods.size() > 65535) {            throw new IllegalArgumentException("method limit exceeded");        }        if (fields.size() > 65535) {            throw new IllegalArgumentException("field limit exceeded");        }         /* ============================================================         * Step 3: Write the final class file.         */         /*         * Make sure that constant pool indexes are reserved for the         * following items before starting to write the final class file.         */        cp.getClass(dotToSlash(className));        cp.getClass(superclassName);        for (int i = 0; i < interfaces.length; i++) {            cp.getClass(dotToSlash(interfaces[i].getName()));        }         /*         * Disallow new constant pool additions beyond this point, since         * we are about to write the final constant pool table.         */        cp.setReadOnly();         ByteArrayOutputStream bout = new ByteArrayOutputStream();        DataOutputStream dout = new DataOutputStream(bout);         try {            /*             * Write all the items of the "ClassFile" structure.             * See JVMS section 4.1.             */

Lines 1–500 of 2009.