712 lines · 27.8 KB · Java
RawDownload
/* * Copyright (c) 2001, 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.reflect; import java.lang.reflect.*;import sun.misc.Unsafe; /** Shared functionality for all accessor generators */ class AccessorGenerator implements ClassFileConstants {    static final Unsafe unsafe = Unsafe.getUnsafe();     // Constants because there's no way to say "short integer constant",    // i.e., "1S"    protected static final short S0 = (short) 0;    protected static final short S1 = (short) 1;    protected static final short S2 = (short) 2;    protected static final short S3 = (short) 3;    protected static final short S4 = (short) 4;    protected static final short S5 = (short) 5;    protected static final short S6 = (short) 6;     // Instance variables for shared functionality between    // FieldAccessorGenerator and MethodAccessorGenerator    protected ClassFileAssembler asm;    protected int   modifiers;    protected short thisClass;    protected short superClass;    protected short targetClass;    // Common constant pool entries to FieldAccessor and MethodAccessor    protected short throwableClass;    protected short classCastClass;    protected short nullPointerClass;    protected short illegalArgumentClass;    protected short invocationTargetClass;    protected short initIdx;    protected short initNameAndTypeIdx;    protected short initStringNameAndTypeIdx;    protected short nullPointerCtorIdx;    protected short illegalArgumentCtorIdx;    protected short illegalArgumentStringCtorIdx;    protected short invocationTargetCtorIdx;    protected short superCtorIdx;    protected short objectClass;    protected short toStringIdx;    protected short codeIdx;    protected short exceptionsIdx;    // Boxing    protected short booleanIdx;    protected short booleanCtorIdx;    protected short booleanUnboxIdx;    protected short byteIdx;    protected short byteCtorIdx;    protected short byteUnboxIdx;    protected short characterIdx;    protected short characterCtorIdx;    protected short characterUnboxIdx;    protected short doubleIdx;    protected short doubleCtorIdx;    protected short doubleUnboxIdx;    protected short floatIdx;    protected short floatCtorIdx;    protected short floatUnboxIdx;    protected short integerIdx;    protected short integerCtorIdx;    protected short integerUnboxIdx;    protected short longIdx;    protected short longCtorIdx;    protected short longUnboxIdx;    protected short shortIdx;    protected short shortCtorIdx;    protected short shortUnboxIdx;     protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;    protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 72;     // Requires that superClass has been set up    protected void emitCommonConstantPoolEntries() {        // +   [UTF-8] "java/lang/Throwable"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "java/lang/ClassCastException"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "java/lang/NullPointerException"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "java/lang/IllegalArgumentException"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "java/lang/InvocationTargetException"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "<init>"        // +   [UTF-8] "()V"        // +   [CONSTANT_NameAndType_info] for above        // +   [CONSTANT_Methodref_info] for NullPointerException's constructor        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor        // +   [UTF-8] "(Ljava/lang/String;)V"        // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String        // +   [UTF-8] "(Ljava/lang/Throwable;)V"        // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"        // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor        // +   [CONSTANT_Methodref_info] for "super()"        // +   [UTF-8] "java/lang/Object"        // +   [CONSTANT_Class_info] for above        // +   [UTF-8] "toString"        // +   [UTF-8] "()Ljava/lang/String;"        // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"        // +   [CONSTANT_Methodref_info] for Object's toString method        // +   [UTF-8] "Code"        // +   [UTF-8] "Exceptions"        asm.emitConstantPoolUTF8("java/lang/Throwable");        asm.emitConstantPoolClass(asm.cpi());        throwableClass = asm.cpi();        asm.emitConstantPoolUTF8("java/lang/ClassCastException");        asm.emitConstantPoolClass(asm.cpi());        classCastClass = asm.cpi();        asm.emitConstantPoolUTF8("java/lang/NullPointerException");        asm.emitConstantPoolClass(asm.cpi());        nullPointerClass = asm.cpi();        asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException");        asm.emitConstantPoolClass(asm.cpi());        illegalArgumentClass = asm.cpi();        asm.emitConstantPoolUTF8("java/lang/reflect/InvocationTargetException");        asm.emitConstantPoolClass(asm.cpi());        invocationTargetClass = asm.cpi();        asm.emitConstantPoolUTF8("<init>");        initIdx = asm.cpi();        asm.emitConstantPoolUTF8("()V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        initNameAndTypeIdx = asm.cpi();        asm.emitConstantPoolMethodref(nullPointerClass, initNameAndTypeIdx);        nullPointerCtorIdx = asm.cpi();        asm.emitConstantPoolMethodref(illegalArgumentClass, initNameAndTypeIdx);        illegalArgumentCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("(Ljava/lang/String;)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        initStringNameAndTypeIdx = asm.cpi();        asm.emitConstantPoolMethodref(illegalArgumentClass, initStringNameAndTypeIdx);        illegalArgumentStringCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi());        invocationTargetCtorIdx = asm.cpi();        asm.emitConstantPoolMethodref(superClass, initNameAndTypeIdx);        superCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("java/lang/Object");        asm.emitConstantPoolClass(asm.cpi());        objectClass = asm.cpi();        asm.emitConstantPoolUTF8("toString");        asm.emitConstantPoolUTF8("()Ljava/lang/String;");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(objectClass, asm.cpi());        toStringIdx = asm.cpi();        asm.emitConstantPoolUTF8("Code");        codeIdx = asm.cpi();        asm.emitConstantPoolUTF8("Exceptions");        exceptionsIdx = asm.cpi();    }     /** Constant pool entries required to be able to box/unbox primitive        types. Note that we don't emit these if we don't need them. */    protected void emitBoxingContantPoolEntries() {        //  *  [UTF-8] "java/lang/Boolean"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(Z)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "booleanValue"        //  *  [UTF-8] "()Z"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Byte"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(B)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "byteValue"        //  *  [UTF-8] "()B"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Character"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(C)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "charValue"        //  *  [UTF-8] "()C"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Double"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(D)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "doubleValue"        //  *  [UTF-8] "()D"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Float"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(F)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "floatValue"        //  *  [UTF-8] "()F"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Integer"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(I)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "intValue"        //  *  [UTF-8] "()I"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Long"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(J)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "longValue"        //  *  [UTF-8] "()J"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "java/lang/Short"        //  *  [CONSTANT_Class_info] for above        //  *  [UTF-8] "(S)V"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        //  *  [UTF-8] "shortValue"        //  *  [UTF-8] "()S"        //  *  [CONSTANT_NameAndType_info] for above        //  *  [CONSTANT_Methodref_info] for above        // Boolean        asm.emitConstantPoolUTF8("java/lang/Boolean");        asm.emitConstantPoolClass(asm.cpi());        booleanIdx = asm.cpi();        asm.emitConstantPoolUTF8("(Z)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        booleanCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("booleanValue");        asm.emitConstantPoolUTF8("()Z");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        booleanUnboxIdx = asm.cpi();         // Byte        asm.emitConstantPoolUTF8("java/lang/Byte");        asm.emitConstantPoolClass(asm.cpi());        byteIdx = asm.cpi();        asm.emitConstantPoolUTF8("(B)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        byteCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("byteValue");        asm.emitConstantPoolUTF8("()B");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        byteUnboxIdx = asm.cpi();         // Character        asm.emitConstantPoolUTF8("java/lang/Character");        asm.emitConstantPoolClass(asm.cpi());        characterIdx = asm.cpi();        asm.emitConstantPoolUTF8("(C)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        characterCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("charValue");        asm.emitConstantPoolUTF8("()C");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        characterUnboxIdx = asm.cpi();         // Double        asm.emitConstantPoolUTF8("java/lang/Double");        asm.emitConstantPoolClass(asm.cpi());        doubleIdx = asm.cpi();        asm.emitConstantPoolUTF8("(D)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        doubleCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("doubleValue");        asm.emitConstantPoolUTF8("()D");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        doubleUnboxIdx = asm.cpi();         // Float        asm.emitConstantPoolUTF8("java/lang/Float");        asm.emitConstantPoolClass(asm.cpi());        floatIdx = asm.cpi();        asm.emitConstantPoolUTF8("(F)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        floatCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("floatValue");        asm.emitConstantPoolUTF8("()F");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        floatUnboxIdx = asm.cpi();         // Integer        asm.emitConstantPoolUTF8("java/lang/Integer");        asm.emitConstantPoolClass(asm.cpi());        integerIdx = asm.cpi();        asm.emitConstantPoolUTF8("(I)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        integerCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("intValue");        asm.emitConstantPoolUTF8("()I");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        integerUnboxIdx = asm.cpi();         // Long        asm.emitConstantPoolUTF8("java/lang/Long");        asm.emitConstantPoolClass(asm.cpi());        longIdx = asm.cpi();        asm.emitConstantPoolUTF8("(J)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        longCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("longValue");        asm.emitConstantPoolUTF8("()J");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        longUnboxIdx = asm.cpi();         // Short        asm.emitConstantPoolUTF8("java/lang/Short");        asm.emitConstantPoolClass(asm.cpi());        shortIdx = asm.cpi();        asm.emitConstantPoolUTF8("(S)V");        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());        shortCtorIdx = asm.cpi();        asm.emitConstantPoolUTF8("shortValue");        asm.emitConstantPoolUTF8("()S");        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());        shortUnboxIdx = asm.cpi();    }     // Necessary because of Java's annoying promotion rules    protected static short add(short s1, short s2) {        return (short) (s1 + s2);    }     protected static short sub(short s1, short s2) {        return (short) (s1 - s2);    }     protected boolean isStatic() {        return Modifier.isStatic(modifiers);    }     /** Returns class name in "internal" form (i.e., '/' separators        instead of '.') */    protected static String getClassName        (Class c, boolean addPrefixAndSuffixForNonPrimitiveTypes)    {        if (c.isPrimitive()) {            if (c == Boolean.TYPE) {                return "Z";            } else if (c == Byte.TYPE) {                return "B";            } else if (c == Character.TYPE) {                return "C";            } else if (c == Double.TYPE) {                return "D";            } else if (c == Float.TYPE) {                return "F";            } else if (c == Integer.TYPE) {                return "I";            } else if (c == Long.TYPE) {                return "J";            } else if (c == Short.TYPE) {                return "S";            } else if (c == Void.TYPE) {                return "V";            }            throw new InternalError("Should have found primitive type");        } else if (c.isArray()) {            return "[" + getClassName(c.getComponentType(), true);        } else {            if (addPrefixAndSuffixForNonPrimitiveTypes) {                return internalize("L" + c.getName() + ";");            } else {                return internalize(c.getName());            }        }    }     private static String internalize(String className) {        return className.replace('.', '/');    }     protected void emitConstructor() {        // Generate code into fresh code buffer        ClassFileAssembler cb = new ClassFileAssembler();        // 0 incoming arguments        cb.setMaxLocals(1);        cb.opc_aload_0();        cb.opc_invokespecial(superCtorIdx, 0, 0);        cb.opc_return();         // Emit method        emitMethod(initIdx, cb.getMaxLocals(), cb, null, null);    }     // The descriptor's index in the constant pool must be (1 +    // nameIdx). "numArgs" must indicate ALL arguments, including the    // implicit "this" argument; double and long arguments each count    // as 2 in this count. The code buffer must NOT contain the code    // length. The exception table may be null, but if non-null must    // NOT contain the exception table's length. The checked exception    // indices may be null.    protected void emitMethod(short nameIdx,                              int numArgs,                              ClassFileAssembler code,                              ClassFileAssembler exceptionTable,                              short[] checkedExceptionIndices)    {        int codeLen = code.getLength();        int excLen  = 0;        if (exceptionTable != null) {            excLen = exceptionTable.getLength();            if ((excLen % 8) != 0) {                throw new IllegalArgumentException("Illegal exception table");            }        }        int attrLen = 12 + codeLen + excLen;        excLen = excLen / 8; // No-op if no exception table         asm.emitShort(ACC_PUBLIC);        asm.emitShort(nameIdx);        asm.emitShort(add(nameIdx, S1));        if (checkedExceptionIndices == null) {            // Code attribute only            asm.emitShort(S1);        } else {            // Code and Exceptions attributes            asm.emitShort(S2);        }        // Code attribute        asm.emitShort(codeIdx);        asm.emitInt(attrLen);        asm.emitShort(code.getMaxStack());        asm.emitShort((short) Math.max(numArgs, code.getMaxLocals()));        asm.emitInt(codeLen);        asm.append(code);        asm.emitShort((short) excLen);        if (exceptionTable != null) {            asm.append(exceptionTable);        }        asm.emitShort(S0); // No additional attributes for Code attribute        if (checkedExceptionIndices != null) {            // Exceptions attribute            asm.emitShort(exceptionsIdx);            asm.emitInt(2 + 2 * checkedExceptionIndices.length);            asm.emitShort((short) checkedExceptionIndices.length);            for (int i = 0; i < checkedExceptionIndices.length; i++) {                asm.emitShort(checkedExceptionIndices[i]);            }        }    }     protected short indexForPrimitiveType(Class type) {        if (type == Boolean.TYPE) {            return booleanIdx;        } else if (type == Byte.TYPE) {            return byteIdx;        } else if (type == Character.TYPE) {            return characterIdx;        } else if (type == Double.TYPE) {

Lines 1–500 of 712.