diff options
author | Alkalus <draknyte1@hotmail.com> | 2020-03-31 02:40:07 +0000 |
---|---|---|
committer | Alkalus <draknyte1@hotmail.com> | 2020-03-31 02:40:07 +0000 |
commit | 6d6adf8039fb97f2025610eb313a4caa48df838b (patch) | |
tree | 80e377c85c8a89edeac671cc6b2f2655a150f41e /src/Java/sun | |
parent | 47816dec7729bde0bf247ff7db8ebf6b25b92048 (diff) | |
parent | 8a8048a6418ca8da9de0bd7b49f6ec39f9b0aad6 (diff) | |
download | GT5-Unofficial-6d6adf8039fb97f2025610eb313a4caa48df838b.tar.gz GT5-Unofficial-6d6adf8039fb97f2025610eb313a4caa48df838b.tar.bz2 GT5-Unofficial-6d6adf8039fb97f2025610eb313a4caa48df838b.zip |
Merged in AlkWork (pull request #4)
AlkWork
Diffstat (limited to 'src/Java/sun')
38 files changed, 11328 insertions, 0 deletions
diff --git a/src/Java/sun/repackage/AccessorGenerator.java b/src/Java/sun/repackage/AccessorGenerator.java new file mode 100644 index 0000000000..054d90be78 --- /dev/null +++ b/src/Java/sun/repackage/AccessorGenerator.java @@ -0,0 +1,715 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.lang.reflect.*; + +/** 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); + } + + protected boolean isPrivate() { + return Modifier.isPrivate(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) { + return doubleIdx; + } else if (type == Float.TYPE) { + return floatIdx; + } else if (type == Integer.TYPE) { + return integerIdx; + } else if (type == Long.TYPE) { + return longIdx; + } else if (type == Short.TYPE) { + return shortIdx; + } + throw new InternalError("Should have found primitive type"); + } + + protected short ctorIndexForPrimitiveType(Class<?> type) { + if (type == Boolean.TYPE) { + return booleanCtorIdx; + } else if (type == Byte.TYPE) { + return byteCtorIdx; + } else if (type == Character.TYPE) { + return characterCtorIdx; + } else if (type == Double.TYPE) { + return doubleCtorIdx; + } else if (type == Float.TYPE) { + return floatCtorIdx; + } else if (type == Integer.TYPE) { + return integerCtorIdx; + } else if (type == Long.TYPE) { + return longCtorIdx; + } else if (type == Short.TYPE) { + return shortCtorIdx; + } + throw new InternalError("Should have found primitive type"); + } + + /** Returns true for widening or identity conversions for primitive + types only */ + protected static boolean canWidenTo(Class<?> type, Class<?> otherType) { + if (!type.isPrimitive()) { + return false; + } + + // Widening conversions (from JVM spec): + // byte to short, int, long, float, or double + // short to int, long, float, or double + // char to int, long, float, or double + // int to long, float, or double + // long to float or double + // float to double + + if (type == Boolean.TYPE) { + if (otherType == Boolean.TYPE) { + return true; + } + } else if (type == Byte.TYPE) { + if ( otherType == Byte.TYPE + || otherType == Short.TYPE + || otherType == Integer.TYPE + || otherType == Long.TYPE + || otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Short.TYPE) { + if ( otherType == Short.TYPE + || otherType == Integer.TYPE + || otherType == Long.TYPE + || otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Character.TYPE) { + if ( otherType == Character.TYPE + || otherType == Integer.TYPE + || otherType == Long.TYPE + || otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Integer.TYPE) { + if ( otherType == Integer.TYPE + || otherType == Long.TYPE + || otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Long.TYPE) { + if ( otherType == Long.TYPE + || otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Float.TYPE) { + if ( otherType == Float.TYPE + || otherType == Double.TYPE) { + return true; + } + } else if (type == Double.TYPE) { + if (otherType == Double.TYPE) { + return true; + } + } + + return false; + } + + /** Emits the widening bytecode for the given primitive conversion + (or none if the identity conversion). Requires that a primitive + conversion exists; i.e., canWidenTo must have already been + called and returned true. */ + protected static void emitWideningBytecodeForPrimitiveConversion + (ClassFileAssembler cb, + Class<?> fromType, + Class<?> toType) + { + // Note that widening conversions for integral types (i.e., "b2s", + // "s2i") are no-ops since values on the Java stack are + // sign-extended. + + // Widening conversions (from JVM spec): + // byte to short, int, long, float, or double + // short to int, long, float, or double + // char to int, long, float, or double + // int to long, float, or double + // long to float or double + // float to double + + if ( fromType == Byte.TYPE + || fromType == Short.TYPE + || fromType == Character.TYPE + || fromType == Integer.TYPE) { + if (toType == Long.TYPE) { + cb.opc_i2l(); + } else if (toType == Float.TYPE) { + cb.opc_i2f(); + } else if (toType == Double.TYPE) { + cb.opc_i2d(); + } + } else if (fromType == Long.TYPE) { + if (toType == Float.TYPE) { + cb.opc_l2f(); + } else if (toType == Double.TYPE) { + cb.opc_l2d(); + } + } else if (fromType == Float.TYPE) { + if (toType == Double.TYPE) { + cb.opc_f2d(); + } + } + + // Otherwise, was identity or no-op conversion. Fall through. + } + + protected short unboxingMethodForPrimitiveType(Class<?> primType) { + if (primType == Boolean.TYPE) { + return booleanUnboxIdx; + } else if (primType == Byte.TYPE) { + return byteUnboxIdx; + } else if (primType == Character.TYPE) { + return characterUnboxIdx; + } else if (primType == Short.TYPE) { + return shortUnboxIdx; + } else if (primType == Integer.TYPE) { + return integerUnboxIdx; + } else if (primType == Long.TYPE) { + return longUnboxIdx; + } else if (primType == Float.TYPE) { + return floatUnboxIdx; + } else if (primType == Double.TYPE) { + return doubleUnboxIdx; + } + throw new InternalError("Illegal primitive type " + primType.getName()); + } + + protected static final Class<?>[] primitiveTypes = new Class<?>[] { + Boolean.TYPE, + Byte.TYPE, + Character.TYPE, + Short.TYPE, + Integer.TYPE, + Long.TYPE, + Float.TYPE, + Double.TYPE + }; + + /** We don't consider "Void" to be a primitive type */ + protected static boolean isPrimitive(Class<?> c) { + return (c.isPrimitive() && c != Void.TYPE); + } + + protected int typeSizeInStackSlots(Class<?> c) { + if (c == Void.TYPE) { + return 0; + } + if (c == Long.TYPE || c == Double.TYPE) { + return 2; + } + return 1; + } + + private ClassFileAssembler illegalArgumentCodeBuffer; + protected ClassFileAssembler illegalArgumentCodeBuffer() { + if (illegalArgumentCodeBuffer == null) { + illegalArgumentCodeBuffer = new ClassFileAssembler(); + illegalArgumentCodeBuffer.opc_new(illegalArgumentClass); + illegalArgumentCodeBuffer.opc_dup(); + illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); + illegalArgumentCodeBuffer.opc_athrow(); + } + + return illegalArgumentCodeBuffer; + } +} diff --git a/src/Java/sun/repackage/BootstrapConstructorAccessorImpl.java b/src/Java/sun/repackage/BootstrapConstructorAccessorImpl.java new file mode 100644 index 0000000000..b7b5a72372 --- /dev/null +++ b/src/Java/sun/repackage/BootstrapConstructorAccessorImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +import java.lang.reflect.Constructor; + +/** Uses Unsafe.allocateObject() to instantiate classes; only used for + bootstrapping. */ + +class BootstrapConstructorAccessorImpl extends ConstructorAccessorImpl { + private final Constructor<?> constructor; + + BootstrapConstructorAccessorImpl(Constructor<?> c) { + this.constructor = c; + } + + public Object newInstance(Object[] args) + throws IllegalArgumentException, InvocationTargetException + { + try { + return UnsafeFieldAccessorImpl.unsafe. + allocateInstance(constructor.getDeclaringClass()); + } catch (InstantiationException e) { + throw new InvocationTargetException(e); + } + } +} diff --git a/src/Java/sun/repackage/ByteVector.java b/src/Java/sun/repackage/ByteVector.java new file mode 100644 index 0000000000..7c6cc5cc12 --- /dev/null +++ b/src/Java/sun/repackage/ByteVector.java @@ -0,0 +1,37 @@ +/* + * 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.repackage; + +/** A growable array of bytes. */ + +interface ByteVector { + public int getLength(); + public byte get(int index); + public void put(int index, byte value); + public void add(byte value); + public void trim(); + public byte[] getData(); +} diff --git a/src/Java/sun/repackage/ByteVectorFactory.java b/src/Java/sun/repackage/ByteVectorFactory.java new file mode 100644 index 0000000000..110373db8b --- /dev/null +++ b/src/Java/sun/repackage/ByteVectorFactory.java @@ -0,0 +1,36 @@ +/* + * 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.repackage; + +class ByteVectorFactory { + static ByteVector create() { + return new ByteVectorImpl(); + } + + static ByteVector create(int sz) { + return new ByteVectorImpl(sz); + } +} diff --git a/src/Java/sun/repackage/ByteVectorImpl.java b/src/Java/sun/repackage/ByteVectorImpl.java new file mode 100644 index 0000000000..b04667ce53 --- /dev/null +++ b/src/Java/sun/repackage/ByteVectorImpl.java @@ -0,0 +1,88 @@ +/* + * 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.repackage; + +class ByteVectorImpl implements ByteVector { + private byte[] data; + private int pos; + + public ByteVectorImpl() { + this(100); + } + + public ByteVectorImpl(int sz) { + data = new byte[sz]; + pos = -1; + } + + public int getLength() { + return pos + 1; + } + + public byte get(int index) { + if (index >= data.length) { + resize(index); + pos = index; + } + return data[index]; + } + + public void put(int index, byte value) { + if (index >= data.length) { + resize(index); + pos = index; + } + data[index] = value; + } + + public void add(byte value) { + if (++pos >= data.length) { + resize(pos); + } + data[pos] = value; + } + + public void trim() { + if (pos != data.length - 1) { + byte[] newData = new byte[pos + 1]; + System.arraycopy(data, 0, newData, 0, pos + 1); + data = newData; + } + } + + public byte[] getData() { + return data; + } + + private void resize(int minSize) { + if (minSize <= 2 * data.length) { + minSize = 2 * data.length; + } + byte[] newData = new byte[minSize]; + System.arraycopy(data, 0, newData, 0, data.length); + data = newData; + } +} diff --git a/src/Java/sun/repackage/CallerSensitive.java b/src/Java/sun/repackage/CallerSensitive.java new file mode 100644 index 0000000000..9a9a07171b --- /dev/null +++ b/src/Java/sun/repackage/CallerSensitive.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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.repackage; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; + +/** + * A method annotated @CallerSensitive is sensitive to its calling class, + * via {@link sun.repackage.Reflection#getCallerClass Reflection.getCallerClass}, + * or via some equivalent. + * + * @author John R. Rose + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({METHOD}) +public @interface CallerSensitive { +} diff --git a/src/Java/sun/repackage/ClassDefiner.java b/src/Java/sun/repackage/ClassDefiner.java new file mode 100644 index 0000000000..e9b3cb2e1d --- /dev/null +++ b/src/Java/sun/repackage/ClassDefiner.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** Utility class which assists in calling Unsafe.defineClass() by + creating a new class loader which delegates to the one needed in + order for proper resolution of the given bytecodes to occur. */ + +class ClassDefiner { + static final Unsafe unsafe = Unsafe.getUnsafe(); + + /** <P> We define generated code into a new class loader which + delegates to the defining loader of the target class. It is + necessary for the VM to be able to resolve references to the + target class from the generated bytecodes, which could not occur + if the generated code was loaded into the bootstrap class + loader. </P> + + <P> There are two primary reasons for creating a new loader + instead of defining these bytecodes directly into the defining + loader of the target class: first, it avoids any possible + security risk of having these bytecodes in the same loader. + Second, it allows the generated bytecodes to be unloaded earlier + than would otherwise be possible, decreasing run-time + footprint. </P> + */ + static Class<?> defineClass(String name, byte[] bytes, int off, int len, + final ClassLoader parentClassLoader) + { + ClassLoader newLoader = AccessController.doPrivileged( + new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return new DelegatingClassLoader(parentClassLoader); + } + }); + return unsafe.defineClass(name, bytes, off, len, newLoader, null); + } +} + + +// NOTE: this class's name and presence are known to the virtual +// machine as of the fix for 4474172. +class DelegatingClassLoader extends ClassLoader { + DelegatingClassLoader(ClassLoader parent) { + super(parent); + } +} diff --git a/src/Java/sun/repackage/ClassFileAssembler.java b/src/Java/sun/repackage/ClassFileAssembler.java new file mode 100644 index 0000000000..f17be6824e --- /dev/null +++ b/src/Java/sun/repackage/ClassFileAssembler.java @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2001, 2004, 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.repackage; + +class ClassFileAssembler implements ClassFileConstants { + private ByteVector vec; + private short cpIdx = 0; + + public ClassFileAssembler() { + this(ByteVectorFactory.create()); + } + + public ClassFileAssembler(ByteVector vec) { + this.vec = vec; + } + + public ByteVector getData() { + return vec; + } + + /** Length in bytes */ + public short getLength() { + return (short) vec.getLength(); + } + + public void emitMagicAndVersion() { + emitInt(0xCAFEBABE); + emitShort((short) 0); + emitShort((short) 49); + } + + public void emitInt(int val) { + emitByte((byte) (val >> 24)); + emitByte((byte) ((val >> 16) & 0xFF)); + emitByte((byte) ((val >> 8) & 0xFF)); + emitByte((byte) (val & 0xFF)); + } + + public void emitShort(short val) { + emitByte((byte) ((val >> 8) & 0xFF)); + emitByte((byte) (val & 0xFF)); + } + + // Support for labels; package-private + void emitShort(short bci, short val) { + vec.put(bci, (byte) ((val >> 8) & 0xFF)); + vec.put(bci + 1, (byte) (val & 0xFF)); + } + + public void emitByte(byte val) { + vec.add(val); + } + + public void append(ClassFileAssembler asm) { + append(asm.vec); + } + + public void append(ByteVector vec) { + for (int i = 0; i < vec.getLength(); i++) { + emitByte(vec.get(i)); + } + } + + /** Keeps track of the current (one-based) constant pool index; + incremented after emitting one of the following constant pool + entries. Can fetch the current constant pool index for use in + later entries. Index points at the last valid constant pool + entry; initially invalid. It is illegal to fetch the constant + pool index before emitting at least one constant pool entry. */ + public short cpi() { + if (cpIdx == 0) { + throw new RuntimeException("Illegal use of ClassFileAssembler"); + } + return cpIdx; + } + + public void emitConstantPoolUTF8(String str) { + // NOTE: can not use str.getBytes("UTF-8") here because of + // bootstrapping issues with the character set converters. + byte[] bytes = UTF8.encode(str); + emitByte(CONSTANT_Utf8); + emitShort((short) bytes.length); + for (int i = 0; i < bytes.length; i++) { + emitByte(bytes[i]); + } + cpIdx++; + } + + public void emitConstantPoolClass(short index) { + emitByte(CONSTANT_Class); + emitShort(index); + cpIdx++; + } + + public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) { + emitByte(CONSTANT_NameAndType); + emitShort(nameIndex); + emitShort(typeIndex); + cpIdx++; + } + + public void emitConstantPoolFieldref + (short classIndex, short nameAndTypeIndex) + { + emitByte(CONSTANT_Fieldref); + emitShort(classIndex); + emitShort(nameAndTypeIndex); + cpIdx++; + } + + public void emitConstantPoolMethodref + (short classIndex, short nameAndTypeIndex) + { + emitByte(CONSTANT_Methodref); + emitShort(classIndex); + emitShort(nameAndTypeIndex); + cpIdx++; + } + + public void emitConstantPoolInterfaceMethodref + (short classIndex, short nameAndTypeIndex) + { + emitByte(CONSTANT_InterfaceMethodref); + emitShort(classIndex); + emitShort(nameAndTypeIndex); + cpIdx++; + } + + public void emitConstantPoolString(short utf8Index) { + emitByte(CONSTANT_String); + emitShort(utf8Index); + cpIdx++; + } + + //---------------------------------------------------------------------- + // Opcodes. Keeps track of maximum stack and locals. Make a new + // assembler for each piece of assembled code, then append the + // result to the previous assembler's class file. + // + + private int stack = 0; + private int maxStack = 0; + private int maxLocals = 0; + + private void incStack() { + setStack(stack + 1); + } + + private void decStack() { + --stack; + } + + public short getMaxStack() { + return (short) maxStack; + } + + public short getMaxLocals() { + return (short) maxLocals; + } + + /** It's necessary to be able to specify the number of arguments at + the beginning of the method (which translates to the initial + value of max locals) */ + public void setMaxLocals(int maxLocals) { + this.maxLocals = maxLocals; + } + + /** Needed to do flow control. Returns current stack depth. */ + public int getStack() { + return stack; + } + + /** Needed to do flow control. */ + public void setStack(int value) { + stack = value; + if (stack > maxStack) { + maxStack = stack; + } + } + + /////////////// + // Constants // + /////////////// + + public void opc_aconst_null() { + emitByte(opc_aconst_null); + incStack(); + } + + public void opc_sipush(short constant) { + emitByte(opc_sipush); + emitShort(constant); + incStack(); + } + + public void opc_ldc(byte cpIdx) { + emitByte(opc_ldc); + emitByte(cpIdx); + incStack(); + } + + ///////////////////////////////////// + // Local variable loads and stores // + ///////////////////////////////////// + + public void opc_iload_0() { + emitByte(opc_iload_0); + if (maxLocals < 1) maxLocals = 1; + incStack(); + } + + public void opc_iload_1() { + emitByte(opc_iload_1); + if (maxLocals < 2) maxLocals = 2; + incStack(); + } + + public void opc_iload_2() { + emitByte(opc_iload_2); + if (maxLocals < 3) maxLocals = 3; + incStack(); + } + + public void opc_iload_3() { + emitByte(opc_iload_3); + if (maxLocals < 4) maxLocals = 4; + incStack(); + } + + public void opc_lload_0() { + emitByte(opc_lload_0); + if (maxLocals < 2) maxLocals = 2; + incStack(); + incStack(); + } + + public void opc_lload_1() { + emitByte(opc_lload_1); + if (maxLocals < 3) maxLocals = 3; + incStack(); + incStack(); + } + + public void opc_lload_2() { + emitByte(opc_lload_2); + if (maxLocals < 4) maxLocals = 4; + incStack(); + incStack(); + } + + public void opc_lload_3() { + emitByte(opc_lload_3); + if (maxLocals < 5) maxLocals = 5; + incStack(); + incStack(); + } + + public void opc_fload_0() { + emitByte(opc_fload_0); + if (maxLocals < 1) maxLocals = 1; + incStack(); + } + + public void opc_fload_1() { + emitByte(opc_fload_1); + if (maxLocals < 2) maxLocals = 2; + incStack(); + } + + public void opc_fload_2() { + emitByte(opc_fload_2); + if (maxLocals < 3) maxLocals = 3; + incStack(); + } + + public void opc_fload_3() { + emitByte(opc_fload_3); + if (maxLocals < 4) maxLocals = 4; + incStack(); + } + + public void opc_dload_0() { + emitByte(opc_dload_0); + if (maxLocals < 2) maxLocals = 2; + incStack(); + incStack(); + } + + public void opc_dload_1() { + emitByte(opc_dload_1); + if (maxLocals < 3) maxLocals = 3; + incStack(); + incStack(); + } + + public void opc_dload_2() { + emitByte(opc_dload_2); + if (maxLocals < 4) maxLocals = 4; + incStack(); + incStack(); + } + + public void opc_dload_3() { + emitByte(opc_dload_3); + if (maxLocals < 5) maxLocals = 5; + incStack(); + incStack(); + } + + public void opc_aload_0() { + emitByte(opc_aload_0); + if (maxLocals < 1) maxLocals = 1; + incStack(); + } + + public void opc_aload_1() { + emitByte(opc_aload_1); + if (maxLocals < 2) maxLocals = 2; + incStack(); + } + + public void opc_aload_2() { + emitByte(opc_aload_2); + if (maxLocals < 3) maxLocals = 3; + incStack(); + } + + public void opc_aload_3() { + emitByte(opc_aload_3); + if (maxLocals < 4) maxLocals = 4; + incStack(); + } + + public void opc_aaload() { + emitByte(opc_aaload); + decStack(); + } + + public void opc_astore_0() { + emitByte(opc_astore_0); + if (maxLocals < 1) maxLocals = 1; + decStack(); + } + + public void opc_astore_1() { + emitByte(opc_astore_1); + if (maxLocals < 2) maxLocals = 2; + decStack(); + } + + public void opc_astore_2() { + emitByte(opc_astore_2); + if (maxLocals < 3) maxLocals = 3; + decStack(); + } + + public void opc_astore_3() { + emitByte(opc_astore_3); + if (maxLocals < 4) maxLocals = 4; + decStack(); + } + + //////////////////////// + // Stack manipulation // + //////////////////////// + + public void opc_pop() { + emitByte(opc_pop); + decStack(); + } + + public void opc_dup() { + emitByte(opc_dup); + incStack(); + } + + public void opc_dup_x1() { + emitByte(opc_dup_x1); + incStack(); + } + + public void opc_swap() { + emitByte(opc_swap); + } + + /////////////////////////////// + // Widening conversions only // + /////////////////////////////// + + public void opc_i2l() { + emitByte(opc_i2l); + } + + public void opc_i2f() { + emitByte(opc_i2f); + } + + public void opc_i2d() { + emitByte(opc_i2d); + } + + public void opc_l2f() { + emitByte(opc_l2f); + } + + public void opc_l2d() { + emitByte(opc_l2d); + } + + public void opc_f2d() { + emitByte(opc_f2d); + } + + ////////////////// + // Control flow // + ////////////////// + + public void opc_ifeq(short bciOffset) { + emitByte(opc_ifeq); + emitShort(bciOffset); + decStack(); + } + + /** Control flow with forward-reference BCI. Stack assumes + straight-through control flow. */ + public void opc_ifeq(Label l) { + short instrBCI = getLength(); + emitByte(opc_ifeq); + l.add(this, instrBCI, getLength(), getStack() - 1); + emitShort((short) -1); // Must be patched later + } + + public void opc_if_icmpeq(short bciOffset) { + emitByte(opc_if_icmpeq); + emitShort(bciOffset); + setStack(getStack() - 2); + } + + /** Control flow with forward-reference BCI. Stack assumes straight + control flow. */ + public void opc_if_icmpeq(Label l) { + short instrBCI = getLength(); + emitByte(opc_if_icmpeq); + l.add(this, instrBCI, getLength(), getStack() - 2); + emitShort((short) -1); // Must be patched later + } + + public void opc_goto(short bciOffset) { + emitByte(opc_goto); + emitShort(bciOffset); + } + + /** Control flow with forward-reference BCI. Stack assumes straight + control flow. */ + public void opc_goto(Label l) { + short instrBCI = getLength(); + emitByte(opc_goto); + l.add(this, instrBCI, getLength(), getStack()); + emitShort((short) -1); // Must be patched later + } + + public void opc_ifnull(short bciOffset) { + emitByte(opc_ifnull); + emitShort(bciOffset); + decStack(); + } + + /** Control flow with forward-reference BCI. Stack assumes straight + control flow. */ + public void opc_ifnull(Label l) { + short instrBCI = getLength(); + emitByte(opc_ifnull); + l.add(this, instrBCI, getLength(), getStack() - 1); + emitShort((short) -1); // Must be patched later + decStack(); + } + + public void opc_ifnonnull(short bciOffset) { + emitByte(opc_ifnonnull); + emitShort(bciOffset); + decStack(); + } + + /** Control flow with forward-reference BCI. Stack assumes straight + control flow. */ + public void opc_ifnonnull(Label l) { + short instrBCI = getLength(); + emitByte(opc_ifnonnull); + l.add(this, instrBCI, getLength(), getStack() - 1); + emitShort((short) -1); // Must be patched later + decStack(); + } + + ///////////////////////// + // Return instructions // + ///////////////////////// + + public void opc_ireturn() { + emitByte(opc_ireturn); + setStack(0); + } + + public void opc_lreturn() { + emitByte(opc_lreturn); + setStack(0); + } + + public void opc_freturn() { + emitByte(opc_freturn); + setStack(0); + } + + public void opc_dreturn() { + emitByte(opc_dreturn); + setStack(0); + } + + public void opc_areturn() { + emitByte(opc_areturn); + setStack(0); + } + + public void opc_return() { + emitByte(opc_return); + setStack(0); + } + + ////////////////////// + // Field operations // + ////////////////////// + + public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) { + emitByte(opc_getstatic); + emitShort(fieldIndex); + setStack(getStack() + fieldSizeInStackSlots); + } + + public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) { + emitByte(opc_putstatic); + emitShort(fieldIndex); + setStack(getStack() - fieldSizeInStackSlots); + } + + public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) { + emitByte(opc_getfield); + emitShort(fieldIndex); + setStack(getStack() + fieldSizeInStackSlots - 1); + } + + public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) { + emitByte(opc_putfield); + emitShort(fieldIndex); + setStack(getStack() - fieldSizeInStackSlots - 1); + } + + //////////////////////// + // Method invocations // + //////////////////////// + + /** Long and double arguments and return types count as 2 arguments; + other values count as 1. */ + public void opc_invokevirtual(short methodIndex, + int numArgs, + int numReturnValues) + { + emitByte(opc_invokevirtual); + emitShort(methodIndex); + setStack(getStack() - numArgs - 1 + numReturnValues); + } + + /** Long and double arguments and return types count as 2 arguments; + other values count as 1. */ + public void opc_invokespecial(short methodIndex, + int numArgs, + int numReturnValues) + { + emitByte(opc_invokespecial); + emitShort(methodIndex); + setStack(getStack() - numArgs - 1 + numReturnValues); + } + + /** Long and double arguments and return types count as 2 arguments; + other values count as 1. */ + public void opc_invokestatic(short methodIndex, + int numArgs, + int numReturnValues) + { + emitByte(opc_invokestatic); + emitShort(methodIndex); + setStack(getStack() - numArgs + numReturnValues); + } + + /** Long and double arguments and return types count as 2 arguments; + other values count as 1. */ + public void opc_invokeinterface(short methodIndex, + int numArgs, + byte count, + int numReturnValues) + { + emitByte(opc_invokeinterface); + emitShort(methodIndex); + emitByte(count); + emitByte((byte) 0); + setStack(getStack() - numArgs - 1 + numReturnValues); + } + + ////////////////// + // Array length // + ////////////////// + + public void opc_arraylength() { + emitByte(opc_arraylength); + } + + ///////// + // New // + ///////// + + public void opc_new(short classIndex) { + emitByte(opc_new); + emitShort(classIndex); + incStack(); + } + + //////////// + // Athrow // + //////////// + + public void opc_athrow() { + emitByte(opc_athrow); + setStack(1); + } + + ////////////////////////////// + // Checkcast and instanceof // + ////////////////////////////// + + /** Assumes the checkcast succeeds */ + public void opc_checkcast(short classIndex) { + emitByte(opc_checkcast); + emitShort(classIndex); + } + + public void opc_instanceof(short classIndex) { + emitByte(opc_instanceof); + emitShort(classIndex); + } +} diff --git a/src/Java/sun/repackage/ClassFileConstants.java b/src/Java/sun/repackage/ClassFileConstants.java new file mode 100644 index 0000000000..7c08b9d533 --- /dev/null +++ b/src/Java/sun/repackage/ClassFileConstants.java @@ -0,0 +1,140 @@ +/* + * 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.repackage; + +/** Minimal set of class file constants for assembly of field and + method accessors. */ + +interface ClassFileConstants { + // Constants + public static final byte opc_aconst_null = (byte) 0x1; + public static final byte opc_sipush = (byte) 0x11; + public static final byte opc_ldc = (byte) 0x12; + + // Local variable loads and stores + public static final byte opc_iload_0 = (byte) 0x1a; + public static final byte opc_iload_1 = (byte) 0x1b; + public static final byte opc_iload_2 = (byte) 0x1c; + public static final byte opc_iload_3 = (byte) 0x1d; + public static final byte opc_lload_0 = (byte) 0x1e; + public static final byte opc_lload_1 = (byte) 0x1f; + public static final byte opc_lload_2 = (byte) 0x20; + public static final byte opc_lload_3 = (byte) 0x21; + public static final byte opc_fload_0 = (byte) 0x22; + public static final byte opc_fload_1 = (byte) 0x23; + public static final byte opc_fload_2 = (byte) 0x24; + public static final byte opc_fload_3 = (byte) 0x25; + public static final byte opc_dload_0 = (byte) 0x26; + public static final byte opc_dload_1 = (byte) 0x27; + public static final byte opc_dload_2 = (byte) 0x28; + public static final byte opc_dload_3 = (byte) 0x29; + public static final byte opc_aload_0 = (byte) 0x2a; + public static final byte opc_aload_1 = (byte) 0x2b; + public static final byte opc_aload_2 = (byte) 0x2c; + public static final byte opc_aload_3 = (byte) 0x2d; + public static final byte opc_aaload = (byte) 0x32; + public static final byte opc_astore_0 = (byte) 0x4b; + public static final byte opc_astore_1 = (byte) 0x4c; + public static final byte opc_astore_2 = (byte) 0x4d; + public static final byte opc_astore_3 = (byte) 0x4e; + + // Stack manipulation + public static final byte opc_pop = (byte) 0x57; + public static final byte opc_dup = (byte) 0x59; + public static final byte opc_dup_x1 = (byte) 0x5a; + public static final byte opc_swap = (byte) 0x5f; + + // Conversions + public static final byte opc_i2l = (byte) 0x85; + public static final byte opc_i2f = (byte) 0x86; + public static final byte opc_i2d = (byte) 0x87; + public static final byte opc_l2i = (byte) 0x88; + public static final byte opc_l2f = (byte) 0x89; + public static final byte opc_l2d = (byte) 0x8a; + public static final byte opc_f2i = (byte) 0x8b; + public static final byte opc_f2l = (byte) 0x8c; + public static final byte opc_f2d = (byte) 0x8d; + public static final byte opc_d2i = (byte) 0x8e; + public static final byte opc_d2l = (byte) 0x8f; + public static final byte opc_d2f = (byte) 0x90; + public static final byte opc_i2b = (byte) 0x91; + public static final byte opc_i2c = (byte) 0x92; + public static final byte opc_i2s = (byte) 0x93; + + // Control flow + public static final byte opc_ifeq = (byte) 0x99; + public static final byte opc_if_icmpeq = (byte) 0x9f; + public static final byte opc_goto = (byte) 0xa7; + + // Return instructions + public static final byte opc_ireturn = (byte) 0xac; + public static final byte opc_lreturn = (byte) 0xad; + public static final byte opc_freturn = (byte) 0xae; + public static final byte opc_dreturn = (byte) 0xaf; + public static final byte opc_areturn = (byte) 0xb0; + public static final byte opc_return = (byte) 0xb1; + + // Field operations + public static final byte opc_getstatic = (byte) 0xb2; + public static final byte opc_putstatic = (byte) 0xb3; + public static final byte opc_getfield = (byte) 0xb4; + public static final byte opc_putfield = (byte) 0xb5; + + // Method invocations + public static final byte opc_invokevirtual = (byte) 0xb6; + public static final byte opc_invokespecial = (byte) 0xb7; + public static final byte opc_invokestatic = (byte) 0xb8; + public static final byte opc_invokeinterface = (byte) 0xb9; + + // Array length + public static final byte opc_arraylength = (byte) 0xbe; + + // New + public static final byte opc_new = (byte) 0xbb; + + // Athrow + public static final byte opc_athrow = (byte) 0xbf; + + // Checkcast and instanceof + public static final byte opc_checkcast = (byte) 0xc0; + public static final byte opc_instanceof = (byte) 0xc1; + + // Ifnull and ifnonnull + public static final byte opc_ifnull = (byte) 0xc6; + public static final byte opc_ifnonnull = (byte) 0xc7; + + // Constant pool tags + public static final byte CONSTANT_Class = (byte) 7; + public static final byte CONSTANT_Fieldref = (byte) 9; + public static final byte CONSTANT_Methodref = (byte) 10; + public static final byte CONSTANT_InterfaceMethodref = (byte) 11; + public static final byte CONSTANT_NameAndType = (byte) 12; + public static final byte CONSTANT_String = (byte) 8; + public static final byte CONSTANT_Utf8 = (byte) 1; + + // Access flags + public static final short ACC_PUBLIC = (short) 0x0001; +} diff --git a/src/Java/sun/repackage/ConstructorAccessor.java b/src/Java/sun/repackage/ConstructorAccessor.java new file mode 100644 index 0000000000..988fb8e5fc --- /dev/null +++ b/src/Java/sun/repackage/ConstructorAccessor.java @@ -0,0 +1,41 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** This interface provides the declaration for + java.lang.reflect.Constructor.invoke(). Each Constructor object is + configured with a (possibly dynamically-generated) class which + implements this interface. */ + +public interface ConstructorAccessor { + /** Matches specification in {@link java.lang.reflect.Constructor} */ + public Object newInstance(Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException; +} diff --git a/src/Java/sun/repackage/ConstructorAccessorImpl.java b/src/Java/sun/repackage/ConstructorAccessorImpl.java new file mode 100644 index 0000000000..22f9d54080 --- /dev/null +++ b/src/Java/sun/repackage/ConstructorAccessorImpl.java @@ -0,0 +1,41 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** Package-private implementation of the ConstructorAccessor + interface which has access to all classes and all fields, + regardless of language restrictions. See MagicAccessorImpl. */ + +abstract class ConstructorAccessorImpl extends MagicAccessorImpl + implements ConstructorAccessor { + /** Matches specification in {@link java.lang.reflect.Constructor} */ + public abstract Object newInstance(Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException; +} diff --git a/src/Java/sun/repackage/DelegatingConstructorAccessorImpl.java b/src/Java/sun/repackage/DelegatingConstructorAccessorImpl.java new file mode 100644 index 0000000000..81a1d4ffc6 --- /dev/null +++ b/src/Java/sun/repackage/DelegatingConstructorAccessorImpl.java @@ -0,0 +1,51 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** Delegates its invocation to another ConstructorAccessorImpl and can + change its delegate at run time. */ + +class DelegatingConstructorAccessorImpl extends ConstructorAccessorImpl { + private ConstructorAccessorImpl delegate; + + DelegatingConstructorAccessorImpl(ConstructorAccessorImpl delegate) { + setDelegate(delegate); + } + + public Object newInstance(Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException + { + return delegate.newInstance(args); + } + + void setDelegate(ConstructorAccessorImpl delegate) { + this.delegate = delegate; + } +} diff --git a/src/Java/sun/repackage/DelegatingMethodAccessorImpl.java b/src/Java/sun/repackage/DelegatingMethodAccessorImpl.java new file mode 100644 index 0000000000..05c825f327 --- /dev/null +++ b/src/Java/sun/repackage/DelegatingMethodAccessorImpl.java @@ -0,0 +1,49 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** Delegates its invocation to another MethodAccessorImpl and can + change its delegate at run time. */ + +class DelegatingMethodAccessorImpl extends MethodAccessorImpl { + private MethodAccessorImpl delegate; + + DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) { + setDelegate(delegate); + } + + public Object invoke(Object obj, Object[] args) + throws IllegalArgumentException, InvocationTargetException + { + return delegate.invoke(obj, args); + } + + void setDelegate(MethodAccessorImpl delegate) { + this.delegate = delegate; + } +} diff --git a/src/Java/sun/repackage/FieldAccessor.java b/src/Java/sun/repackage/FieldAccessor.java new file mode 100644 index 0000000000..6c8e2e16d3 --- /dev/null +++ b/src/Java/sun/repackage/FieldAccessor.java @@ -0,0 +1,96 @@ +/* + * 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.repackage; + +/** This interface provides the declarations for the accessor methods + of java.lang.reflect.Field. Each Field object is configured with a + (possibly dynamically-generated) class which implements this + interface. */ + +public interface FieldAccessor { + /** Matches specification in {@link java.lang.reflect.Field} */ + public Object get(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public boolean getBoolean(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public byte getByte(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public char getChar(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public short getShort(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public int getInt(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public long getLong(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public float getFloat(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public double getDouble(Object obj) throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException; +} diff --git a/src/Java/sun/repackage/FieldAccessorImpl.java b/src/Java/sun/repackage/FieldAccessorImpl.java new file mode 100644 index 0000000000..d49a49e79d --- /dev/null +++ b/src/Java/sun/repackage/FieldAccessorImpl.java @@ -0,0 +1,105 @@ +/* + * 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.repackage; + +/** Package-private implementation of the FieldAccessor interface + which has access to all classes and all fields, regardless of + language restrictions. See MagicAccessorImpl. */ + +abstract class FieldAccessorImpl extends MagicAccessorImpl + implements FieldAccessor { + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract Object get(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract boolean getBoolean(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract byte getByte(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract char getChar(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract short getShort(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract int getInt(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract long getLong(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract float getFloat(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract double getDouble(Object obj) + throws IllegalArgumentException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException; + + /** Matches specification in {@link java.lang.reflect.Field} */ + public abstract void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException; +} diff --git a/src/Java/sun/repackage/ForgeEnumHelper.java b/src/Java/sun/repackage/ForgeEnumHelper.java new file mode 100644 index 0000000000..2f7732574c --- /dev/null +++ b/src/Java/sun/repackage/ForgeEnumHelper.java @@ -0,0 +1,70 @@ +package sun.repackage; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import gtPlusPlus.core.util.reflect.ReflectionUtils; +import gtPlusPlus.preloader.Preloader_Logger; +import net.minecraftforge.common.util.EnumHelper; + +public class ForgeEnumHelper { + private static Object reflectionFactory = null; + private static Method newConstructorAccessor = null; + private static Method newInstance = null; + private static Method newFieldAccessor = null; + private static Method fieldAccessorSet = null; + private static boolean isSetup = false; + + + public static void setup() + { + if (isSetup) + { + return; + } + + try + { + + Preloader_Logger.INFO("Patching Fields in Forge's EnumHelper."); + + Class aRefFac = ReflectionUtils.getClass("sun.repackage.ReflectionFactory"); + Class aConAcc = ReflectionUtils.getClass("sun.repackage.ConstructorAccessor"); + Class aFieAcc = ReflectionUtils.getClass("sun.repackage.FieldAccessor"); + + Method getReflectionFactory = ReflectionUtils.getMethod(aRefFac, "getReflectionFactory", new Class[] {}); + reflectionFactory = ReflectionUtils.invokeNonBool(aRefFac, getReflectionFactory, new Object[] {}); + newConstructorAccessor = ReflectionUtils.getMethod(aRefFac, "newConstructorAccessor", new Class[] {Constructor.class}); + newFieldAccessor = ReflectionUtils.getMethod(aRefFac, "newFieldAccessor", new Class[] {Field.class, boolean.class}); + newInstance = ReflectionUtils.getMethod(aConAcc, "newInstance", new Class[] {Object[].class}); + fieldAccessorSet = ReflectionUtils.getMethod(aFieAcc, "set", new Class[] {Object.class, Object.class}); + + Field aIsSetup = ReflectionUtils.getField(EnumHelper.class, "isSetup"); + Field aReflectionFactory = ReflectionUtils.getField(EnumHelper.class, "reflectionFactory"); + Field aNewConstructorAccessor = ReflectionUtils.getField(EnumHelper.class, "newConstructorAccessor"); + Field aNewInstance = ReflectionUtils.getField(EnumHelper.class, "newInstance"); + Field aNewFieldAccessor = ReflectionUtils.getField(EnumHelper.class, "newFieldAccessor"); + Field aFieldAccessorSet = ReflectionUtils.getField(EnumHelper.class, "fieldAccessorSet"); + + ReflectionUtils.setField(EnumHelper.class, aIsSetup, true); + ReflectionUtils.setField(EnumHelper.class, aReflectionFactory, reflectionFactory); + ReflectionUtils.setField(EnumHelper.class, aNewConstructorAccessor, newConstructorAccessor); + ReflectionUtils.setField(EnumHelper.class, aNewInstance, newInstance); + ReflectionUtils.setField(EnumHelper.class, aNewFieldAccessor, newFieldAccessor); + ReflectionUtils.setField(EnumHelper.class, aFieldAccessorSet, fieldAccessorSet); + + Preloader_Logger.INFO("Finished patching Fields in Forge's EnumHelper."); + + Preloader_Logger.INFO("Testing: "+ReflectionUtils.getFieldValue(aReflectionFactory).getClass().getCanonicalName()); + + } + catch (Exception e) + { + e.printStackTrace(); + } + + isSetup = true; + } + +}
\ No newline at end of file diff --git a/src/Java/sun/repackage/InstantiationExceptionConstructorAccessorImpl.java b/src/Java/sun/repackage/InstantiationExceptionConstructorAccessorImpl.java new file mode 100644 index 0000000000..ca9ca1cff3 --- /dev/null +++ b/src/Java/sun/repackage/InstantiationExceptionConstructorAccessorImpl.java @@ -0,0 +1,51 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** Throws an InstantiationException with given error message upon + newInstance() call */ + +class InstantiationExceptionConstructorAccessorImpl + extends ConstructorAccessorImpl { + private final String message; + + InstantiationExceptionConstructorAccessorImpl(String message) { + this.message = message; + } + + public Object newInstance(Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException + { + if (message == null) { + throw new InstantiationException(); + } + throw new InstantiationException(message); + } +} diff --git a/src/Java/sun/repackage/Label.java b/src/Java/sun/repackage/Label.java new file mode 100644 index 0000000000..86acf54fe6 --- /dev/null +++ b/src/Java/sun/repackage/Label.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +import java.util.List; +import java.util.ArrayList; + +/** Allows forward references in bytecode streams emitted by + ClassFileAssembler. Assumes that the start of the method body is + the first byte in the assembler's buffer. May be used at more than + one branch site. */ + +class Label { + static class PatchInfo { + PatchInfo(ClassFileAssembler asm, + short instrBCI, + short patchBCI, + int stackDepth) + { + this.asm = asm; + this.instrBCI = instrBCI; + this.patchBCI = patchBCI; + this.stackDepth = stackDepth; + } + // This won't work for more than one assembler anyway, so this is + // unnecessary + final ClassFileAssembler asm; + final short instrBCI; + final short patchBCI; + final int stackDepth; + } + private List<PatchInfo> patches = new ArrayList<>(); + + public Label() { + } + + void add(ClassFileAssembler asm, + short instrBCI, + short patchBCI, + int stackDepth) + { + patches.add(new PatchInfo(asm, instrBCI, patchBCI, stackDepth)); + } + + public void bind() { + for (PatchInfo patch : patches){ + short curBCI = patch.asm.getLength(); + short offset = (short) (curBCI - patch.instrBCI); + patch.asm.emitShort(patch.patchBCI, offset); + patch.asm.setStack(patch.stackDepth); + } + } +} diff --git a/src/Java/sun/repackage/LangReflectAccess.java b/src/Java/sun/repackage/LangReflectAccess.java new file mode 100644 index 0000000000..0adfc3cfe2 --- /dev/null +++ b/src/Java/sun/repackage/LangReflectAccess.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.lang.reflect.*; + +/** An interface which gives privileged packages Java-level access to + internals of java.lang.reflect. */ + +public interface LangReflectAccess { + /** Creates a new java.lang.reflect.Field. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Field newField(Class<?> declaringClass, + String name, + Class<?> type, + int modifiers, + int slot, + String signature, + byte[] annotations); + + /** Creates a new java.lang.reflect.Method. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Method newMethod(Class<?> declaringClass, + String name, + Class<?>[] parameterTypes, + Class<?> returnType, + Class<?>[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations, + byte[] annotationDefault); + + /** Creates a new java.lang.reflect.Constructor. Access checks as + per java.lang.reflect.AccessibleObject are not overridden. */ + public <T> Constructor<T> newConstructor(Class<T> declaringClass, + Class<?>[] parameterTypes, + Class<?>[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations); + + /** Gets the MethodAccessor object for a java.lang.reflect.Method */ + public MethodAccessor getMethodAccessor(Method m); + + /** Sets the MethodAccessor object for a java.lang.reflect.Method */ + public void setMethodAccessor(Method m, MethodAccessor accessor); + + /** Gets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public ConstructorAccessor getConstructorAccessor(Constructor<?> c); + + /** Sets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public void setConstructorAccessor(Constructor<?> c, + ConstructorAccessor accessor); + + /** Gets the byte[] that encodes TypeAnnotations on an Executable. */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex); + + /** Gets the "slot" field from a Constructor (used for serialization) */ + public int getConstructorSlot(Constructor<?> c); + + /** Gets the "signature" field from a Constructor (used for serialization) */ + public String getConstructorSignature(Constructor<?> c); + + /** Gets the "annotations" field from a Constructor (used for serialization) */ + public byte[] getConstructorAnnotations(Constructor<?> c); + + /** Gets the "parameterAnnotations" field from a Constructor (used for serialization) */ + public byte[] getConstructorParameterAnnotations(Constructor<?> c); + + // + // Copying routines, needed to quickly fabricate new Field, + // Method, and Constructor objects from templates + // + + /** Makes a "child" copy of a Method */ + public Method copyMethod(Method arg); + + /** Makes a "child" copy of a Field */ + public Field copyField(Field arg); + + /** Makes a "child" copy of a Constructor */ + public <T> Constructor<T> copyConstructor(Constructor<T> arg); +} diff --git a/src/Java/sun/repackage/MagicAccessorImpl.java b/src/Java/sun/repackage/MagicAccessorImpl.java new file mode 100644 index 0000000000..2a335cb08c --- /dev/null +++ b/src/Java/sun/repackage/MagicAccessorImpl.java @@ -0,0 +1,47 @@ +/* + * 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.repackage; + +/** <P> MagicAccessorImpl (named for parity with FieldAccessorImpl and + others, not because it actually implements an interface) is a + marker class in the hierarchy. All subclasses of this class are + "magically" granted access by the VM to otherwise inaccessible + fields and methods of other classes. It is used to hold the code + for dynamically-generated FieldAccessorImpl and MethodAccessorImpl + subclasses. (Use of the word "unsafe" was avoided in this class's + name to avoid confusion with sun.misc.Unsafe.) </P> + + <P> The bug fix for 4486457 also necessitated disabling + verification for this class and all subclasses, as opposed to just + SerializationConstructorAccessorImpl and subclasses, to avoid + having to indicate to the VM which of these dynamically-generated + stub classes were known to be able to pass the verifier. </P> + + <P> Do not change the name of this class without also changing the + VM's code. </P> */ + +class MagicAccessorImpl { +} diff --git a/src/Java/sun/repackage/MethodAccessor.java b/src/Java/sun/repackage/MethodAccessor.java new file mode 100644 index 0000000000..9d70011beb --- /dev/null +++ b/src/Java/sun/repackage/MethodAccessor.java @@ -0,0 +1,40 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** This interface provides the declaration for + java.lang.reflect.Method.invoke(). Each Method object is + configured with a (possibly dynamically-generated) class which + implements this interface. +*/ + +public interface MethodAccessor { + /** Matches specification in {@link java.lang.reflect.Method} */ + public Object invoke(Object obj, Object[] args) + throws IllegalArgumentException, InvocationTargetException; +} diff --git a/src/Java/sun/repackage/MethodAccessorGenerator.java b/src/Java/sun/repackage/MethodAccessorGenerator.java new file mode 100644 index 0000000000..21eae8174f --- /dev/null +++ b/src/Java/sun/repackage/MethodAccessorGenerator.java @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** Generator for sun.reflect.MethodAccessor and + sun.reflect.ConstructorAccessor objects using bytecodes to + implement reflection. A java.lang.reflect.Method or + java.lang.reflect.Constructor object can delegate its invoke or + newInstance method to an accessor using native code or to one + generated by this class. (Methods and Constructors were merged + together in this class to ensure maximum code sharing.) */ + +class MethodAccessorGenerator extends AccessorGenerator { + + private static final short NUM_BASE_CPOOL_ENTRIES = (short) 12; + // One for invoke() plus one for constructor + private static final short NUM_METHODS = (short) 2; + // Only used if forSerialization is true + private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2; + + private static volatile int methodSymnum = 0; + private static volatile int constructorSymnum = 0; + private static volatile int serializationConstructorSymnum = 0; + + private Class<?> declaringClass; + private Class<?>[] parameterTypes; + private Class<?> returnType; + private boolean isConstructor; + private boolean forSerialization; + + private short targetMethodRef; + private short invokeIdx; + private short invokeDescriptorIdx; + // Constant pool index of CONSTANT_Class_info for first + // non-primitive parameter type. Should be incremented by 2. + private short nonPrimitiveParametersBaseIdx; + + MethodAccessorGenerator() { + } + + /** This routine is not thread-safe */ + public MethodAccessor generateMethod(Class<?> declaringClass, + String name, + Class<?>[] parameterTypes, + Class<?> returnType, + Class<?>[] checkedExceptions, + int modifiers) + { + return (MethodAccessor) generate(declaringClass, + name, + parameterTypes, + returnType, + checkedExceptions, + modifiers, + false, + false, + null); + } + + /** This routine is not thread-safe */ + public ConstructorAccessor generateConstructor(Class<?> declaringClass, + Class<?>[] parameterTypes, + Class<?>[] checkedExceptions, + int modifiers) + { + return (ConstructorAccessor) generate(declaringClass, + "<init>", + parameterTypes, + Void.TYPE, + checkedExceptions, + modifiers, + true, + false, + null); + } + + /** This routine is not thread-safe */ + public SerializationConstructorAccessorImpl + generateSerializationConstructor(Class<?> declaringClass, + Class<?>[] parameterTypes, + Class<?>[] checkedExceptions, + int modifiers, + Class<?> targetConstructorClass) + { + return (SerializationConstructorAccessorImpl) + generate(declaringClass, + "<init>", + parameterTypes, + Void.TYPE, + checkedExceptions, + modifiers, + true, + true, + targetConstructorClass); + } + + /** This routine is not thread-safe */ + private MagicAccessorImpl generate(final Class<?> declaringClass, + String name, + Class<?>[] parameterTypes, + Class<?> returnType, + Class<?>[] checkedExceptions, + int modifiers, + boolean isConstructor, + boolean forSerialization, + Class<?> serializationTargetClass) + { + ByteVector vec = ByteVectorFactory.create(); + asm = new ClassFileAssembler(vec); + this.declaringClass = declaringClass; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + this.modifiers = modifiers; + this.isConstructor = isConstructor; + this.forSerialization = forSerialization; + + asm.emitMagicAndVersion(); + + // Constant pool entries: + // ( * = Boxing information: optional) + // (+ = Shared entries provided by AccessorGenerator) + // (^ = Only present if generating SerializationConstructorAccessor) + // [UTF-8] [This class's name] + // [CONSTANT_Class_info] for above + // [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}" + // [CONSTANT_Class_info] for above + // [UTF-8] [Target class's name] + // [CONSTANT_Class_info] for above + // ^ [UTF-8] [Serialization: Class's name in which to invoke constructor] + // ^ [CONSTANT_Class_info] for above + // [UTF-8] target method or constructor name + // [UTF-8] target method or constructor signature + // [CONSTANT_NameAndType_info] for above + // [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method + // [UTF-8] "invoke" or "newInstance" + // [UTF-8] invoke or newInstance descriptor + // [UTF-8] descriptor for type of non-primitive parameter 1 + // [CONSTANT_Class_info] for type of non-primitive parameter 1 + // ... + // [UTF-8] descriptor for type of non-primitive parameter n + // [CONSTANT_Class_info] for type of non-primitive parameter n + // + [UTF-8] "java/lang/Exception" + // + [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" + // * [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 + + short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES; + boolean usesPrimitives = usesPrimitiveTypes(); + if (usesPrimitives) { + numCPEntries += NUM_BOXING_CPOOL_ENTRIES; + } + if (forSerialization) { + numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES; + } + + // Add in variable-length number of entries to be able to describe + // non-primitive parameter types and checked exceptions. + numCPEntries += (short) (2 * numNonPrimitiveParameterTypes()); + + asm.emitShort(add(numCPEntries, S1)); + + final String generatedName = generateName(isConstructor, forSerialization); + asm.emitConstantPoolUTF8(generatedName); + asm.emitConstantPoolClass(asm.cpi()); + thisClass = asm.cpi(); + if (isConstructor) { + if (forSerialization) { + asm.emitConstantPoolUTF8 + ("sun/reflect/SerializationConstructorAccessorImpl"); + } else { + asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl"); + } + } else { + asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl"); + } + asm.emitConstantPoolClass(asm.cpi()); + superClass = asm.cpi(); + asm.emitConstantPoolUTF8(getClassName(declaringClass, false)); + asm.emitConstantPoolClass(asm.cpi()); + targetClass = asm.cpi(); + short serializationTargetClassIdx = (short) 0; + if (forSerialization) { + asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false)); + asm.emitConstantPoolClass(asm.cpi()); + serializationTargetClassIdx = asm.cpi(); + } + asm.emitConstantPoolUTF8(name); + asm.emitConstantPoolUTF8(buildInternalSignature()); + asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); + if (isInterface()) { + asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi()); + } else { + if (forSerialization) { + asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi()); + } else { + asm.emitConstantPoolMethodref(targetClass, asm.cpi()); + } + } + targetMethodRef = asm.cpi(); + if (isConstructor) { + asm.emitConstantPoolUTF8("newInstance"); + } else { + asm.emitConstantPoolUTF8("invoke"); + } + invokeIdx = asm.cpi(); + if (isConstructor) { + asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;"); + } else { + asm.emitConstantPoolUTF8 + ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + } + invokeDescriptorIdx = asm.cpi(); + + // Output class information for non-primitive parameter types + nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2); + for (int i = 0; i < parameterTypes.length; i++) { + Class<?> c = parameterTypes[i]; + if (!isPrimitive(c)) { + asm.emitConstantPoolUTF8(getClassName(c, false)); + asm.emitConstantPoolClass(asm.cpi()); + } + } + + // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor + emitCommonConstantPoolEntries(); + + // Boxing entries + if (usesPrimitives) { + emitBoxingContantPoolEntries(); + } + + if (asm.cpi() != numCPEntries) { + throw new InternalError("Adjust this code (cpi = " + asm.cpi() + + ", numCPEntries = " + numCPEntries + ")"); + } + + // Access flags + asm.emitShort(ACC_PUBLIC); + + // This class + asm.emitShort(thisClass); + + // Superclass + asm.emitShort(superClass); + + // Interfaces count and interfaces + asm.emitShort(S0); + + // Fields count and fields + asm.emitShort(S0); + + // Methods count and methods + asm.emitShort(NUM_METHODS); + + emitConstructor(); + emitInvoke(); + + // Additional attributes (none) + asm.emitShort(S0); + + // Load class + vec.trim(); + final byte[] bytes = vec.getData(); + // Note: the class loader is the only thing that really matters + // here -- it's important to get the generated code into the + // same namespace as the target class. Since the generated code + // is privileged anyway, the protection domain probably doesn't + // matter. + return AccessController.doPrivileged( + new PrivilegedAction<MagicAccessorImpl>() { + public MagicAccessorImpl run() { + try { + return (MagicAccessorImpl) + ClassDefiner.defineClass + (generatedName, + bytes, + 0, + bytes.length, + declaringClass.getClassLoader()).newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new InternalError(e); + } + } + }); + } + + /** This emits the code for either invoke() or newInstance() */ + private void emitInvoke() { + // NOTE that this code will only handle 65535 parameters since we + // use the sipush instruction to get the array index on the + // operand stack. + if (parameterTypes.length > 65535) { + throw new InternalError("Can't handle more than 65535 parameters"); + } + + // Generate code into fresh code buffer + ClassFileAssembler cb = new ClassFileAssembler(); + if (isConstructor) { + // 1 incoming argument + cb.setMaxLocals(2); + } else { + // 2 incoming arguments + cb.setMaxLocals(3); + } + + short illegalArgStartPC = 0; + + if (isConstructor) { + // Instantiate target class before continuing + // new <target class type> + // dup + cb.opc_new(targetClass); + cb.opc_dup(); + } else { + // Setup before iterating down argument list + if (isPrimitive(returnType)) { + // new <boxing type for primitive type> + // dup + // ... (see below:) + // invokespecial <constructor for boxing type for primitive type> + // areturn + cb.opc_new(indexForPrimitiveType(returnType)); + cb.opc_dup(); + } + + // Get target object on operand stack if necessary. + + // We need to do an explicit null check here; we won't see + // NullPointerExceptions from the invoke bytecode, since it's + // covered by an exception handler. + if (!isStatic()) { + // aload_1 + // ifnonnull <checkcast label> + // new <NullPointerException> + // dup + // invokespecial <NullPointerException ctor> + // athrow + // <checkcast label:> + // aload_1 + // checkcast <target class's type> + cb.opc_aload_1(); + Label l = new Label(); + cb.opc_ifnonnull(l); + cb.opc_new(nullPointerClass); + cb.opc_dup(); + cb.opc_invokespecial(nullPointerCtorIdx, 0, 0); + cb.opc_athrow(); + l.bind(); + illegalArgStartPC = cb.getLength(); + cb.opc_aload_1(); + cb.opc_checkcast(targetClass); + } + } + + // Have to check length of incoming array and throw + // IllegalArgumentException if not correct. A concession to the + // JCK (isn't clearly specified in the spec): we allow null in the + // case where the argument list is zero length. + // if no-arg: + // aload_2 | aload_1 (Method | Constructor) + // ifnull <success label> + // aload_2 | aload_1 + // arraylength + // sipush <num parameter types> + // if_icmpeq <success label> + // new <IllegalArgumentException> + // dup + // invokespecial <IllegalArgumentException ctor> + // athrow + // <success label:> + Label successLabel = new Label(); + if (parameterTypes.length == 0) { + if (isConstructor) { + cb.opc_aload_1(); + } else { + cb.opc_aload_2(); + } + cb.opc_ifnull(successLabel); + } + if (isConstructor) { + cb.opc_aload_1(); + } else { + cb.opc_aload_2(); + } + cb.opc_arraylength(); + cb.opc_sipush((short) parameterTypes.length); + cb.opc_if_icmpeq(successLabel); + cb.opc_new(illegalArgumentClass); + cb.opc_dup(); + cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); + cb.opc_athrow(); + successLabel.bind(); + + // Iterate through incoming actual parameters, ensuring that each + // is compatible with the formal parameter type, and pushing the + // actual on the operand stack (unboxing and widening if necessary). + + short paramTypeCPIdx = nonPrimitiveParametersBaseIdx; + Label nextParamLabel = null; + byte count = 1; // both invokeinterface opcode's "count" as well as + // num args of other invoke bytecodes + for (int i = 0; i < parameterTypes.length; i++) { + Class<?> paramType = parameterTypes[i]; + count += (byte) typeSizeInStackSlots(paramType); + if (nextParamLabel != null) { + nextParamLabel.bind(); + nextParamLabel = null; + } + // aload_2 | aload_1 + // sipush <index> + // aaload + if (isConstructor) { + cb.opc_aload_1(); + } else { + cb.opc_aload_2(); + } + cb.opc_sipush((short) i); + cb.opc_aaload(); + if (isPrimitive(paramType)) { + // Unboxing code. + // Put parameter into temporary local variable + // astore_3 | astore_2 + if (isConstructor) { + cb.opc_astore_2(); + } else { + cb.opc_astore_3(); + } + + // repeat for all possible widening conversions: + // aload_3 | aload_2 + // instanceof <primitive boxing type> + // ifeq <next unboxing label> + // aload_3 | aload_2 + // checkcast <primitive boxing type> // Note: this is "redundant", + // // but necessary for the verifier + // invokevirtual <unboxing method> + // <widening conversion bytecode, if necessary> + // goto <next parameter label> + // <next unboxing label:> ... + // last unboxing label: + // new <IllegalArgumentException> + // dup + // invokespecial <IllegalArgumentException ctor> + // athrow + + Label l = null; // unboxing label + nextParamLabel = new Label(); + + for (int j = 0; j < primitiveTypes.length; j++) { + Class<?> c = primitiveTypes[j]; + if (canWidenTo(c, paramType)) { + if (l != null) { + l.bind(); + } + // Emit checking and unboxing code for this type + if (isConstructor) { + cb.opc_aload_2(); + } else { + cb.opc_aload_3(); + } + cb.opc_instanceof(indexForPrimitiveType(c)); + l = new Label(); + cb.opc_ifeq(l); + if (isConstructor) { + cb.opc_aload_2(); + } else { + cb.opc_aload_3(); + } + cb.opc_checkcast(indexForPrimitiveType(c)); + cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c), + 0, + typeSizeInStackSlots(c)); + emitWideningBytecodeForPrimitiveConversion(cb, + c, + paramType); + cb.opc_goto(nextParamLabel); + } + } + + if (l == null) { + throw new InternalError + ("Must have found at least identity conversion"); + } + + // Fell through; given object is null or invalid. According to + // the spec, we can throw IllegalArgumentException for both of + // these cases. + + l.bind(); + cb.opc_new(illegalArgumentClass); + cb.opc_dup(); + cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); + cb.opc_athrow(); + } else { + // Emit appropriate checkcast + cb.opc_checkcast(paramTypeCPIdx); + paramTypeCPIdx = add(paramTypeCPIdx, S2); + // Fall through to next argument + } + } + // Bind last goto if present + if (nextParamLabel != null) { + nextParamLabel.bind(); + } + + short invokeStartPC = cb.getLength(); + + // OK, ready to perform the invocation. + if (isConstructor) { + cb.opc_invokespecial(targetMethodRef, count, 0); + } else { + if (isStatic()) { + cb.opc_invokestatic(targetMethodRef, + count, + typeSizeInStackSlots(returnType)); + } else { + if (isInterface()) { + if (isPrivate()) { + cb.opc_invokespecial(targetMethodRef, count, 0); + } else { + cb.opc_invokeinterface(targetMethodRef, + count, + count, + typeSizeInStackSlots(returnType)); + } + } else { + cb.opc_invokevirtual(targetMethodRef, + count, + typeSizeInStackSlots(returnType)); + } + } + } + + short invokeEndPC = cb.getLength(); + + if (!isConstructor) { + // Box return value if necessary + if (isPrimitive(returnType)) { + cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType), + typeSizeInStackSlots(returnType), + 0); + } else if (returnType == Void.TYPE) { + cb.opc_aconst_null(); + } + } + cb.opc_areturn(); + + // We generate two exception handlers; one which is responsible + // for catching ClassCastException and NullPointerException and + // throwing IllegalArgumentException, and the other which catches + // all java/lang/Throwable objects thrown from the target method + // and wraps them in InvocationTargetExceptions. + + short classCastHandler = cb.getLength(); + + // ClassCast, etc. exception handler + cb.setStack(1); + cb.opc_invokespecial(toStringIdx, 0, 1); + cb.opc_new(illegalArgumentClass); + cb.opc_dup_x1(); + cb.opc_swap(); + cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0); + cb.opc_athrow(); + + short invocationTargetHandler = cb.getLength(); + + // InvocationTargetException exception handler + cb.setStack(1); + cb.opc_new(invocationTargetClass); + cb.opc_dup_x1(); + cb.opc_swap(); + cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0); + cb.opc_athrow(); + + // Generate exception table. We cover the entire code sequence + // with an exception handler which catches ClassCastException and + // converts it into an IllegalArgumentException. + + ClassFileAssembler exc = new ClassFileAssembler(); + + exc.emitShort(illegalArgStartPC); // start PC + exc.emitShort(invokeStartPC); // end PC + exc.emitShort(classCastHandler); // handler PC + exc.emitShort(classCastClass); // catch type + + exc.emitShort(illegalArgStartPC); // start PC + exc.emitShort(invokeStartPC); // end PC + exc.emitShort(classCastHandler); // handler PC + exc.emitShort(nullPointerClass); // catch type + + exc.emitShort(invokeStartPC); // start PC + exc.emitShort(invokeEndPC); // end PC + exc.emitShort(invocationTargetHandler); // handler PC + exc.emitShort(throwableClass); // catch type + + emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc, + new short[] { invocationTargetClass }); + } + + private boolean usesPrimitiveTypes() { + // We need to emit boxing/unboxing constant pool information if + // the method takes a primitive type for any of its parameters or + // returns a primitive value (except void) + if (returnType.isPrimitive()) { + return true; + } + for (int i = 0; i < parameterTypes.length; i++) { + if (parameterTypes[i].isPrimitive()) { + return true; + } + } + return false; + } + + private int numNonPrimitiveParameterTypes() { + int num = 0; + for (int i = 0; i < parameterTypes.length; i++) { + if (!parameterTypes[i].isPrimitive()) { + ++num; + } + } + return num; + } + + private boolean isInterface() { + return declaringClass.isInterface(); + } + + private String buildInternalSignature() { + StringBuffer buf = new StringBuffer(); + buf.append("("); + for (int i = 0; i < parameterTypes.length; i++) { + buf.append(getClassName(parameterTypes[i], true)); + } + buf.append(")"); + buf.append(getClassName(returnType, true)); + return buf.toString(); + } + + private static synchronized String generateName(boolean isConstructor, + boolean forSerialization) + { + if (isConstructor) { + if (forSerialization) { + int num = ++serializationConstructorSymnum; + return "sun/reflect/GeneratedSerializationConstructorAccessor" + num; + } else { + int num = ++constructorSymnum; + return "sun/reflect/GeneratedConstructorAccessor" + num; + } + } else { + int num = ++methodSymnum; + return "sun/reflect/GeneratedMethodAccessor" + num; + } + } +} diff --git a/src/Java/sun/repackage/MethodAccessorImpl.java b/src/Java/sun/repackage/MethodAccessorImpl.java new file mode 100644 index 0000000000..63f7b56aab --- /dev/null +++ b/src/Java/sun/repackage/MethodAccessorImpl.java @@ -0,0 +1,48 @@ +/* + * 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.repackage; + +import java.lang.reflect.InvocationTargetException; + +/** <P> Package-private implementation of the MethodAccessor interface + which has access to all classes and all fields, regardless of + language restrictions. See MagicAccessor. </P> + + <P> This class is known to the VM; do not change its name without + also changing the VM's code. </P> + + <P> NOTE: ALL methods of subclasses are skipped during security + walks up the stack. The assumption is that the only such methods + that will persistently show up on the stack are the implementing + methods for java.lang.reflect.Method.invoke(). </P> +*/ + +abstract class MethodAccessorImpl extends MagicAccessorImpl + implements MethodAccessor { + /** Matches specification in {@link java.lang.reflect.Method} */ + public abstract Object invoke(Object obj, Object[] args) + throws IllegalArgumentException, InvocationTargetException; +} diff --git a/src/Java/sun/repackage/NativeConstructorAccessorImpl.java b/src/Java/sun/repackage/NativeConstructorAccessorImpl.java new file mode 100644 index 0000000000..3acc91e956 --- /dev/null +++ b/src/Java/sun/repackage/NativeConstructorAccessorImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.lang.reflect.*; + +/** Used only for the first few invocations of a Constructor; + afterward, switches to bytecode-based implementation */ + +class NativeConstructorAccessorImpl extends ConstructorAccessorImpl { + private final Constructor<?> c; + private DelegatingConstructorAccessorImpl parent; + private int numInvocations; + + NativeConstructorAccessorImpl(Constructor<?> c) { + this.c = c; + } + + public Object newInstance(Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException + { + // We can't inflate a constructor belonging to a vm-anonymous class + // because that kind of class can't be referred to by name, hence can't + // be found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) { + ConstructorAccessorImpl acc = (ConstructorAccessorImpl) + new MethodAccessorGenerator(). + generateConstructor(c.getDeclaringClass(), + c.getParameterTypes(), + c.getExceptionTypes(), + c.getModifiers()); + parent.setDelegate(acc); + } + + return newInstance0(c, args); + } + + void setParent(DelegatingConstructorAccessorImpl parent) { + this.parent = parent; + } + + private static native Object newInstance0(Constructor<?> c, Object[] args) + throws InstantiationException, + IllegalArgumentException, + InvocationTargetException; +} diff --git a/src/Java/sun/repackage/NativeMethodAccessorImpl.java b/src/Java/sun/repackage/NativeMethodAccessorImpl.java new file mode 100644 index 0000000000..20b6ce9fb0 --- /dev/null +++ b/src/Java/sun/repackage/NativeMethodAccessorImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.lang.reflect.*; + +/** Used only for the first few invocations of a Method; afterward, + switches to bytecode-based implementation */ + +class NativeMethodAccessorImpl extends MethodAccessorImpl { + private final Method method; + private DelegatingMethodAccessorImpl parent; + private int numInvocations; + + NativeMethodAccessorImpl(Method method) { + this.method = method; + } + + public Object invoke(Object obj, Object[] args) + throws IllegalArgumentException, InvocationTargetException + { + // We can't inflate methods belonging to vm-anonymous classes because + // that kind of class can't be referred to by name, hence can't be + // found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) { + MethodAccessorImpl acc = (MethodAccessorImpl) + new MethodAccessorGenerator(). + generateMethod(method.getDeclaringClass(), + method.getName(), + method.getParameterTypes(), + method.getReturnType(), + method.getExceptionTypes(), + method.getModifiers()); + parent.setDelegate(acc); + } + + return invoke0(method, obj, args); + } + + void setParent(DelegatingMethodAccessorImpl parent) { + this.parent = parent; + } + + private static native Object invoke0(Method m, Object obj, Object[] args); +} diff --git a/src/Java/sun/repackage/PermissionFactory.java b/src/Java/sun/repackage/PermissionFactory.java new file mode 100644 index 0000000000..66f614cc9d --- /dev/null +++ b/src/Java/sun/repackage/PermissionFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009, 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.repackage; + +import java.security.Permission; + +/** + * A factory object that creates Permission objects. + */ + +public interface PermissionFactory<T extends Permission> { + T newPermission(String name); +} diff --git a/src/Java/sun/repackage/ReflectUtil.java b/src/Java/sun/repackage/ReflectUtil.java new file mode 100644 index 0000000000..c34b075a73 --- /dev/null +++ b/src/Java/sun/repackage/ReflectUtil.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2005, 2013, 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.repackage; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; + +public final class ReflectUtil { + + private ReflectUtil() { + } + + public static Class<?> forName(String name) + throws ClassNotFoundException { + checkPackageAccess(name); + return Class.forName(name); + } + + public static Object newInstance(Class<?> cls) + throws InstantiationException, IllegalAccessException { + checkPackageAccess(cls); + return cls.newInstance(); + } + + /* + * Reflection.ensureMemberAccess is overly-restrictive + * due to a bug. We awkwardly work around it for now. + */ + public static void ensureMemberAccess(Class<?> currentClass, + Class<?> memberClass, + Object target, + int modifiers) + throws IllegalAccessException + { + if (target == null && Modifier.isProtected(modifiers)) { + int mods = modifiers; + mods = mods & (~Modifier.PROTECTED); + mods = mods | Modifier.PUBLIC; + + /* + * See if we fail because of class modifiers + */ + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + mods); + try { + /* + * We're still here so class access was ok. + * Now try with default field access. + */ + mods = mods & (~Modifier.PUBLIC); + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + mods); + /* + * We're still here so access is ok without + * checking for protected. + */ + return; + } catch (IllegalAccessException e) { + /* + * Access failed but we're 'protected' so + * if the test below succeeds then we're ok. + */ + if (isSubclassOf(currentClass, memberClass)) { + return; + } else { + throw e; + } + } + } else { + Reflection.ensureMemberAccess(currentClass, + memberClass, + target, + modifiers); + } + } + + private static boolean isSubclassOf(Class<?> queryClass, + Class<?> ofClass) + { + while (queryClass != null) { + if (queryClass == ofClass) { + return true; + } + queryClass = queryClass.getSuperclass(); + } + return false; + } + + /** + * Does a conservative approximation of member access check. Use this if + * you don't have an actual 'userland' caller Class/ClassLoader available. + * This might be more restrictive than a precise member access check where + * you have a caller, but should never allow a member access that is + * forbidden. + * + * @param m the {@code Member} about to be accessed + */ + public static void conservativeCheckMemberAccess(Member m) throws SecurityException{ + final SecurityManager sm = System.getSecurityManager(); + if (sm == null) + return; + + // Check for package access on the declaring class. + // + // In addition, unless the member and the declaring class are both + // public check for access declared member permissions. + // + // This is done regardless of ClassLoader relations between the {@code + // Member m} and any potential caller. + + final Class<?> declaringClass = m.getDeclaringClass(); + + checkPackageAccess(declaringClass); + + if (Modifier.isPublic(m.getModifiers()) && + Modifier.isPublic(declaringClass.getModifiers())) + return; + + // Check for declared member access. + sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + } + + /** + * Checks package access on the given class. + * + * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements + * a non-public interface (i.e. may be in a non-restricted package), + * also check the package access on the proxy interfaces. + */ + public static void checkPackageAccess(Class<?> clazz) { + checkPackageAccess(clazz.getName()); + if (isNonPublicProxyClass(clazz)) { + checkProxyPackageAccess(clazz); + } + } + + /** + * Checks package access on the given classname. + * This method is typically called when the Class instance is not + * available and the caller attempts to load a class on behalf + * the true caller (application). + */ + public static void checkPackageAccess(String name) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + String cname = name.replace('/', '.'); + if (cname.startsWith("[")) { + int b = cname.lastIndexOf('[') + 2; + if (b > 1 && b < cname.length()) { + cname = cname.substring(b); + } + } + int i = cname.lastIndexOf('.'); + if (i != -1) { + s.checkPackageAccess(cname.substring(0, i)); + } + } + } + + public static boolean isPackageAccessible(Class<?> clazz) { + try { + checkPackageAccess(clazz); + } catch (SecurityException e) { + return false; + } + return true; + } + + // Returns true if p is an ancestor of cl i.e. class loader 'p' can + // be found in the cl's delegation chain + private static boolean isAncestor(ClassLoader p, ClassLoader cl) { + ClassLoader acl = cl; + do { + acl = acl.getParent(); + if (p == acl) { + return true; + } + } while (acl != null); + return false; + } + + /** + * Returns true if package access check is needed for reflective + * access from a class loader 'from' to classes or members in + * a class defined by class loader 'to'. This method returns true + * if 'from' is not the same as or an ancestor of 'to'. All code + * in a system domain are granted with all permission and so this + * method returns false if 'from' class loader is a class loader + * loading system classes. On the other hand, if a class loader + * attempts to access system domain classes, it requires package + * access check and this method will return true. + */ + public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { + if (from == null || from == to) + return false; + + if (to == null) + return true; + + return !isAncestor(from, to); + } + + /** + * Check package access on the proxy interfaces that the given proxy class + * implements. + * + * @param clazz Proxy class object + */ + public static void checkProxyPackageAccess(Class<?> clazz) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + // check proxy interfaces if the given class is a proxy class + if (Proxy.isProxyClass(clazz)) { + for (Class<?> intf : clazz.getInterfaces()) { + checkPackageAccess(intf); + } + } + } + } + + /** + * Access check on the interfaces that a proxy class implements and throw + * {@code SecurityException} if it accesses a restricted package from + * the caller's class loader. + * + * @param ccl the caller's class loader + * @param interfaces the list of interfaces that a proxy class implements + */ + public static void checkProxyPackageAccess(ClassLoader ccl, + Class<?>... interfaces) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + for (Class<?> intf : interfaces) { + ClassLoader cl = intf.getClassLoader(); + if (needsPackageAccessCheck(ccl, cl)) { + checkPackageAccess(intf); + } + } + } + } + + // Note that bytecode instrumentation tools may exclude 'sun.*' + // classes but not generated proxy classes and so keep it in com.sun.* + public static final String PROXY_PACKAGE = "com.sun.proxy"; + + /** + * Test if the given class is a proxy class that implements + * non-public interface. Such proxy class may be in a non-restricted + * package that bypasses checkPackageAccess. + */ + public static boolean isNonPublicProxyClass(Class<?> cls) { + String name = cls.getName(); + int i = name.lastIndexOf('.'); + String pkg = (i != -1) ? name.substring(0, i) : ""; + return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); + } + + /** + * Check if the given method is a method declared in the proxy interface + * implemented by the given proxy instance. + * + * @param proxy a proxy instance + * @param method an interface method dispatched to a InvocationHandler + * + * @throws IllegalArgumentException if the given proxy or method is invalid. + */ + public static void checkProxyMethod(Object proxy, Method method) { + // check if it is a valid proxy instance + if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { + throw new IllegalArgumentException("Not a Proxy instance"); +} + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalArgumentException("Can't handle static method"); + } + + Class<?> c = method.getDeclaringClass(); + if (c == Object.class) { + String name = method.getName(); + if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { + return; + } + } + + if (isSuperInterface(proxy.getClass(), c)) { + return; + } + + // disallow any method not declared in one of the proxy intefaces + throw new IllegalArgumentException("Can't handle: " + method); + } + + private static boolean isSuperInterface(Class<?> c, Class<?> intf) { + for (Class<?> i : c.getInterfaces()) { + if (i == intf) { + return true; + } + if (isSuperInterface(i, intf)) { + return true; + } + } + return false; + } + + public static boolean isVMAnonymousClass(Class<?> cls) { + return cls.getName().indexOf("/") > -1; + } +} diff --git a/src/Java/sun/repackage/Reflection.java b/src/Java/sun/repackage/Reflection.java new file mode 100644 index 0000000000..8a679db6ec --- /dev/null +++ b/src/Java/sun/repackage/Reflection.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.lang.reflect.*; +import java.util.HashMap; +import java.util.Map; + +/** Common utility routines used by both java.lang and + java.lang.reflect */ + +public class Reflection { + + /** Used to filter out fields and methods from certain classes from public + view, where they are sensitive or they may contain VM-internal objects. + These Maps are updated very rarely. Rather than synchronize on + each access, we use copy-on-write */ + private static volatile Map<Class<?>,String[]> fieldFilterMap; + private static volatile Map<Class<?>,String[]> methodFilterMap; + + static { + Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>(); + map.put(Reflection.class, + new String[] {"fieldFilterMap", "methodFilterMap"}); + map.put(System.class, new String[] {"security"}); + map.put(Class.class, new String[] {"classLoader"}); + fieldFilterMap = map; + + methodFilterMap = new HashMap<>(); + } + + /** Returns the class of the caller of the method calling this method, + ignoring frames associated with java.lang.reflect.Method.invoke() + and its implementation. */ + @CallerSensitive + public static native Class<?> getCallerClass(); + + /** + * @deprecated This method will be removed in JDK 9. + * This method is a private JDK API and retained temporarily for + * existing code to run until a replacement API is defined. + */ + @Deprecated + public static native Class<?> getCallerClass(int depth); + + /** Retrieves the access flags written to the class file. For + inner classes these flags may differ from those returned by + Class.getModifiers(), which searches the InnerClasses + attribute to find the source-level access flags. This is used + instead of Class.getModifiers() for run-time access checks due + to compatibility reasons; see 4471811. Only the values of the + low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be + valid. */ + public static native int getClassAccessFlags(Class<?> c); + + /** A quick "fast-path" check to try to avoid getCallerClass() + calls. */ + public static boolean quickCheckMemberAccess(Class<?> memberClass, + int modifiers) + { + return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers); + } + + public static void ensureMemberAccess(Class<?> currentClass, + Class<?> memberClass, + Object target, + int modifiers) + throws IllegalAccessException + { + if (currentClass == null || memberClass == null) { + throw new InternalError(); + } + + if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) { + throw new IllegalAccessException("Class " + currentClass.getName() + + " can not access a member of class " + + memberClass.getName() + + " with modifiers \"" + + Modifier.toString(modifiers) + + "\""); + } + } + + public static boolean verifyMemberAccess(Class<?> currentClass, + // Declaring class of field + // or method + Class<?> memberClass, + // May be NULL in case of statics + Object target, + int modifiers) + { + // Verify that currentClass can access a field, method, or + // constructor of memberClass, where that member's access bits are + // "modifiers". + + boolean gotIsSameClassPackage = false; + boolean isSameClassPackage = false; + + if (currentClass == memberClass) { + // Always succeeds + return true; + } + + if (!Modifier.isPublic(getClassAccessFlags(memberClass))) { + isSameClassPackage = isSameClassPackage(currentClass, memberClass); + gotIsSameClassPackage = true; + if (!isSameClassPackage) { + return false; + } + } + + // At this point we know that currentClass can access memberClass. + + if (Modifier.isPublic(modifiers)) { + return true; + } + + boolean successSoFar = false; + + if (Modifier.isProtected(modifiers)) { + // See if currentClass is a subclass of memberClass + if (isSubclassOf(currentClass, memberClass)) { + successSoFar = true; + } + } + + if (!successSoFar && !Modifier.isPrivate(modifiers)) { + if (!gotIsSameClassPackage) { + isSameClassPackage = isSameClassPackage(currentClass, + memberClass); + gotIsSameClassPackage = true; + } + + if (isSameClassPackage) { + successSoFar = true; + } + } + + if (!successSoFar) { + return false; + } + + if (Modifier.isProtected(modifiers)) { + // Additional test for protected members: JLS 6.6.2 + Class<?> targetClass = (target == null ? memberClass : target.getClass()); + if (targetClass != currentClass) { + if (!gotIsSameClassPackage) { + isSameClassPackage = isSameClassPackage(currentClass, memberClass); + gotIsSameClassPackage = true; + } + if (!isSameClassPackage) { + if (!isSubclassOf(targetClass, currentClass)) { + return false; + } + } + } + } + + return true; + } + + private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) { + return isSameClassPackage(c1.getClassLoader(), c1.getName(), + c2.getClassLoader(), c2.getName()); + } + + /** Returns true if two classes are in the same package; classloader + and classname information is enough to determine a class's package */ + private static boolean isSameClassPackage(ClassLoader loader1, String name1, + ClassLoader loader2, String name2) + { + if (loader1 != loader2) { + return false; + } else { + int lastDot1 = name1.lastIndexOf('.'); + int lastDot2 = name2.lastIndexOf('.'); + if ((lastDot1 == -1) || (lastDot2 == -1)) { + // One of the two doesn't have a package. Only return true + // if the other one also doesn't have a package. + return (lastDot1 == lastDot2); + } else { + int idx1 = 0; + int idx2 = 0; + + // Skip over '['s + if (name1.charAt(idx1) == '[') { + do { + idx1++; + } while (name1.charAt(idx1) == '['); + if (name1.charAt(idx1) != 'L') { + // Something is terribly wrong. Shouldn't be here. + throw new InternalError("Illegal class name " + name1); + } + } + if (name2.charAt(idx2) == '[') { + do { + idx2++; + } while (name2.charAt(idx2) == '['); + if (name2.charAt(idx2) != 'L') { + // Something is terribly wrong. Shouldn't be here. + throw new InternalError("Illegal class name " + name2); + } + } + + // Check that package part is identical + int length1 = lastDot1 - idx1; + int length2 = lastDot2 - idx2; + + if (length1 != length2) { + return false; + } + return name1.regionMatches(false, idx1, name2, idx2, length1); + } + } + } + + static boolean isSubclassOf(Class<?> queryClass, + Class<?> ofClass) + { + while (queryClass != null) { + if (queryClass == ofClass) { + return true; + } + queryClass = queryClass.getSuperclass(); + } + return false; + } + + // fieldNames must contain only interned Strings + public static synchronized void registerFieldsToFilter(Class<?> containingClass, + String ... fieldNames) { + fieldFilterMap = + registerFilter(fieldFilterMap, containingClass, fieldNames); + } + + // methodNames must contain only interned Strings + public static synchronized void registerMethodsToFilter(Class<?> containingClass, + String ... methodNames) { + methodFilterMap = + registerFilter(methodFilterMap, containingClass, methodNames); + } + + private static Map<Class<?>,String[]> registerFilter(Map<Class<?>,String[]> map, + Class<?> containingClass, String ... names) { + if (map.get(containingClass) != null) { + throw new IllegalArgumentException + ("Filter already registered: " + containingClass); + } + map = new HashMap<Class<?>,String[]>(map); + map.put(containingClass, names); + return map; + } + + public static Field[] filterFields(Class<?> containingClass, + Field[] fields) { + if (fieldFilterMap == null) { + // Bootstrapping + return fields; + } + return (Field[])filter(fields, fieldFilterMap.get(containingClass)); + } + + public static Method[] filterMethods(Class<?> containingClass, Method[] methods) { + if (methodFilterMap == null) { + // Bootstrapping + return methods; + } + return (Method[])filter(methods, methodFilterMap.get(containingClass)); + } + + private static Member[] filter(Member[] members, String[] filteredNames) { + if ((filteredNames == null) || (members.length == 0)) { + return members; + } + int numNewMembers = 0; + for (Member member : members) { + boolean shouldSkip = false; + for (String filteredName : filteredNames) { + if (member.getName() == filteredName) { + shouldSkip = true; + break; + } + } + if (!shouldSkip) { + ++numNewMembers; + } + } + Member[] newMembers = + (Member[])Array.newInstance(members[0].getClass(), numNewMembers); + int destIdx = 0; + for (Member member : members) { + boolean shouldSkip = false; + for (String filteredName : filteredNames) { + if (member.getName() == filteredName) { + shouldSkip = true; + break; + } + } + if (!shouldSkip) { + newMembers[destIdx++] = member; + } + } + return newMembers; + } + + /** + * Tests if the given method is caller-sensitive and the declaring class + * is defined by either the bootstrap class loader or extension class loader. + */ + public static boolean isCallerSensitive(Method m) { + final ClassLoader loader = m.getDeclaringClass().getClassLoader(); + if (isSystemDomainLoader(loader) || isExtClassLoader(loader)) { + return m.isAnnotationPresent(CallerSensitive.class); + } + return false; + } + + private static boolean isExtClassLoader(ClassLoader loader) { + ClassLoader cl = ClassLoader.getSystemClassLoader(); + while (cl != null) { + if (cl.getParent() == null && cl == loader) { + return true; + } + cl = cl.getParent(); + } + return false; + } + + + + /** + * Returns true if the given class loader is in the system domain + * in which all permissions are granted. + */ + public static boolean isSystemDomainLoader(ClassLoader loader) { + return loader == null; + } +} diff --git a/src/Java/sun/repackage/ReflectionFactory.java b/src/Java/sun/repackage/ReflectionFactory.java new file mode 100644 index 0000000000..a1e35a70bb --- /dev/null +++ b/src/Java/sun/repackage/ReflectionFactory.java @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2001, 2013, 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.repackage; + +import java.io.Externalizable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.OptionalDataException; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; +import java.util.Objects; + + +/** <P> The master factory for all reflective objects, both those in + java.lang.reflect (Fields, Methods, Constructors) as well as their + delegates (FieldAccessors, MethodAccessors, ConstructorAccessors). + </P> + + <P> The methods in this class are extremely unsafe and can cause + subversion of both the language and the verifier. For this reason, + they are all instance methods, and access to the constructor of + this factory is guarded by a security check, in similar style to + sun.misc.Unsafe. </P> +*/ + +public class ReflectionFactory { + + private static boolean initted = false; + private static final Permission reflectionFactoryAccessPerm + = new RuntimePermission("reflectionFactoryAccess"); + private static final ReflectionFactory soleInstance = new ReflectionFactory(); + // Provides access to package-private mechanisms in java.lang.reflect + private static volatile LangReflectAccess langReflectAccess; + + /* Method for static class initializer <clinit>, or null */ + private static volatile Method hasStaticInitializerMethod; + + // + // "Inflation" mechanism. Loading bytecodes to implement + // Method.invoke() and Constructor.newInstance() currently costs + // 3-4x more than an invocation via native code for the first + // invocation (though subsequent invocations have been benchmarked + // to be over 20x faster). Unfortunately this cost increases + // startup time for certain applications that use reflection + // intensively (but only once per class) to bootstrap themselves. + // To avoid this penalty we reuse the existing JVM entry points + // for the first few invocations of Methods and Constructors and + // then switch to the bytecode-based implementations. + // + // Package-private to be accessible to NativeMethodAccessorImpl + // and NativeConstructorAccessorImpl + private static boolean noInflation = false; + private static int inflationThreshold = 15; + + private ReflectionFactory() {} + + /** + * A convenience class for acquiring the capability to instantiate + * reflective objects. Use this instead of a raw call to {@link + * #getReflectionFactory} in order to avoid being limited by the + * permissions of your callers. + * + * <p>An instance of this class can be used as the argument of + * <code>AccessController.doPrivileged</code>. + */ + public static final class GetReflectionFactoryAction + implements PrivilegedAction<ReflectionFactory> { + public ReflectionFactory run() { + return getReflectionFactory(); + } + } + + /** + * Provides the caller with the capability to instantiate reflective + * objects. + * + * <p> First, if there is a security manager, its + * <code>checkPermission</code> method is called with a {@link + * java.lang.RuntimePermission} with target + * <code>"reflectionFactoryAccess"</code>. This may result in a + * security exception. + * + * <p> The returned <code>ReflectionFactory</code> object should be + * carefully guarded by the caller, since it can be used to read and + * write private data and invoke private methods, as well as to load + * unverified bytecodes. It must never be passed to untrusted code. + * + * @exception SecurityException if a security manager exists and its + * <code>checkPermission</code> method doesn't allow + * access to the RuntimePermission "reflectionFactoryAccess". */ + public static ReflectionFactory getReflectionFactory() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + // TO DO: security.checkReflectionFactoryAccess(); + security.checkPermission(reflectionFactoryAccessPerm); + } + return soleInstance; + } + + //-------------------------------------------------------------------------- + // + // Routines used by java.lang.reflect + // + // + + /** Called only by java.lang.reflect.Modifier's static initializer */ + public void setLangReflectAccess(LangReflectAccess access) { + langReflectAccess = access; + } + + /** + * Note: this routine can cause the declaring class for the field + * be initialized and therefore must not be called until the + * first get/set of this field. + * @param field the field + * @param override true if caller has overridden aaccessibility + */ + public FieldAccessor newFieldAccessor(Field field, boolean override) { + checkInitted(); + return UnsafeFieldAccessorFactory.newFieldAccessor(field, override); + } + + public MethodAccessor newMethodAccessor(Method method) { + checkInitted(); + + if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) { + return new MethodAccessorGenerator(). + generateMethod(method.getDeclaringClass(), + method.getName(), + method.getParameterTypes(), + method.getReturnType(), + method.getExceptionTypes(), + method.getModifiers()); + } else { + NativeMethodAccessorImpl acc = + new NativeMethodAccessorImpl(method); + DelegatingMethodAccessorImpl res = + new DelegatingMethodAccessorImpl(acc); + acc.setParent(res); + return res; + } + } + + public ConstructorAccessor newConstructorAccessor(Constructor<?> c) { + checkInitted(); + + Class<?> declaringClass = c.getDeclaringClass(); + if (Modifier.isAbstract(declaringClass.getModifiers())) { + return new InstantiationExceptionConstructorAccessorImpl(null); + } + if (declaringClass == Class.class) { + return new InstantiationExceptionConstructorAccessorImpl + ("Can not instantiate java.lang.Class"); + } + // Bootstrapping issue: since we use Class.newInstance() in + // the ConstructorAccessor generation process, we have to + // break the cycle here. + if (Reflection.isSubclassOf(declaringClass, + ConstructorAccessorImpl.class)) { + return new BootstrapConstructorAccessorImpl(c); + } + + if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) { + return new MethodAccessorGenerator(). + generateConstructor(c.getDeclaringClass(), + c.getParameterTypes(), + c.getExceptionTypes(), + c.getModifiers()); + } else { + NativeConstructorAccessorImpl acc = + new NativeConstructorAccessorImpl(c); + DelegatingConstructorAccessorImpl res = + new DelegatingConstructorAccessorImpl(acc); + acc.setParent(res); + return res; + } + } + + //-------------------------------------------------------------------------- + // + // Routines used by java.lang + // + // + + /** Creates a new java.lang.reflect.Field. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Field newField(Class<?> declaringClass, + String name, + Class<?> type, + int modifiers, + int slot, + String signature, + byte[] annotations) + { + return langReflectAccess().newField(declaringClass, + name, + type, + modifiers, + slot, + signature, + annotations); + } + + /** Creates a new java.lang.reflect.Method. Access checks as per + java.lang.reflect.AccessibleObject are not overridden. */ + public Method newMethod(Class<?> declaringClass, + String name, + Class<?>[] parameterTypes, + Class<?> returnType, + Class<?>[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations, + byte[] annotationDefault) + { + return langReflectAccess().newMethod(declaringClass, + name, + parameterTypes, + returnType, + checkedExceptions, + modifiers, + slot, + signature, + annotations, + parameterAnnotations, + annotationDefault); + } + + /** Creates a new java.lang.reflect.Constructor. Access checks as + per java.lang.reflect.AccessibleObject are not overridden. */ + public Constructor<?> newConstructor(Class<?> declaringClass, + Class<?>[] parameterTypes, + Class<?>[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations) + { + return langReflectAccess().newConstructor(declaringClass, + parameterTypes, + checkedExceptions, + modifiers, + slot, + signature, + annotations, + parameterAnnotations); + } + + /** Gets the MethodAccessor object for a java.lang.reflect.Method */ + public MethodAccessor getMethodAccessor(Method m) { + return langReflectAccess().getMethodAccessor(m); + } + + /** Sets the MethodAccessor object for a java.lang.reflect.Method */ + public void setMethodAccessor(Method m, MethodAccessor accessor) { + langReflectAccess().setMethodAccessor(m, accessor); + } + + /** Gets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public ConstructorAccessor getConstructorAccessor(Constructor<?> c) { + return langReflectAccess().getConstructorAccessor(c); + } + + /** Sets the ConstructorAccessor object for a + java.lang.reflect.Constructor */ + public void setConstructorAccessor(Constructor<?> c, + ConstructorAccessor accessor) + { + langReflectAccess().setConstructorAccessor(c, accessor); + } + + /** Makes a copy of the passed method. The returned method is a + "child" of the passed one; see the comments in Method.java for + details. */ + public Method copyMethod(Method arg) { + return langReflectAccess().copyMethod(arg); + } + + /** Makes a copy of the passed field. The returned field is a + "child" of the passed one; see the comments in Field.java for + details. */ + public Field copyField(Field arg) { + return langReflectAccess().copyField(arg); + } + + /** Makes a copy of the passed constructor. The returned + constructor is a "child" of the passed one; see the comments + in Constructor.java for details. */ + public <T> Constructor<T> copyConstructor(Constructor<T> arg) { + return langReflectAccess().copyConstructor(arg); + } + + /** Gets the byte[] that encodes TypeAnnotations on an executable. + */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return langReflectAccess().getExecutableTypeAnnotationBytes(ex); + } + + //-------------------------------------------------------------------------- + // + // Routines used by serialization + // + // + + /** + * Returns an accessible constructor capable of creating instances + * of the given class, initialized by the given constructor. + * + * @param classToInstantiate the class to instantiate + * @param constructorToCall the constructor to call + * @return an accessible constructor + */ + public Constructor<?> newConstructorForSerialization + (Class<?> classToInstantiate, Constructor<?> constructorToCall) + { + // Fast path + if (constructorToCall.getDeclaringClass() == classToInstantiate) { + return constructorToCall; + } + return generateConstructor(classToInstantiate, constructorToCall); + } + + /** + * Returns an accessible no-arg constructor for a class. + * The no-arg constructor is found searching the class and its supertypes. + * + * @param cl the class to instantiate + * @return a no-arg constructor for the class or {@code null} if + * the class or supertypes do not have a suitable no-arg constructor + */ + public final Constructor<?> newConstructorForSerialization(Class<?> cl) { + Class<?> initCl = cl; + while (Serializable.class.isAssignableFrom(initCl)) { + if ((initCl = initCl.getSuperclass()) == null) { + return null; + } + } + Constructor<?> constructorToCall; + try { + constructorToCall = initCl.getDeclaredConstructor(); + int mods = constructorToCall.getModifiers(); + if ((mods & Modifier.PRIVATE) != 0 || + ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && + !packageEquals(cl, initCl))) { + return null; + } + } catch (NoSuchMethodException ex) { + return null; + } + return generateConstructor(cl, constructorToCall); + } + + private final Constructor<?> generateConstructor(Class<?> classToInstantiate, + Constructor<?> constructorToCall) { + + + ConstructorAccessor acc = new MethodAccessorGenerator(). + generateSerializationConstructor(classToInstantiate, + constructorToCall.getParameterTypes(), + constructorToCall.getExceptionTypes(), + constructorToCall.getModifiers(), + constructorToCall.getDeclaringClass()); + Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(), + constructorToCall.getParameterTypes(), + constructorToCall.getExceptionTypes(), + constructorToCall.getModifiers(), + langReflectAccess(). + getConstructorSlot(constructorToCall), + langReflectAccess(). + getConstructorSignature(constructorToCall), + langReflectAccess(). + getConstructorAnnotations(constructorToCall), + langReflectAccess(). + getConstructorParameterAnnotations(constructorToCall)); + setConstructorAccessor(c, acc); + c.setAccessible(true); + return c; + } + + /** + * Returns an accessible no-arg constructor for an externalizable class to be + * initialized using a public no-argument constructor. + * + * @param cl the class to instantiate + * @return A no-arg constructor for the class; returns {@code null} if + * the class does not implement {@link java.io.Externalizable} + */ + public final Constructor<?> newConstructorForExternalization(Class<?> cl) { + if (!Externalizable.class.isAssignableFrom(cl)) { + return null; + } + try { + Constructor<?> cons = cl.getConstructor(); + cons.setAccessible(true); + return cons; + } catch (NoSuchMethodException ex) { + return null; + } + } + + /** + * Returns a direct MethodHandle for the {@code readObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObject} method of the class or + * {@code null} if the class does not have a {@code readObject} method + */ + public final MethodHandle readObjectForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class); + } + + /** + * Returns a direct MethodHandle for the {@code readObjectNoData} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObjectNoData}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObjectNoData} method + * of the class or {@code null} if the class does not have a + * {@code readObjectNoData} method + */ + public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class); + } + + /** + * Returns a direct MethodHandle for the {@code writeObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectOutputStream} passed to + * {@code writeObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code writeObject} method of the class or + * {@code null} if the class does not have a {@code writeObject} method + */ + public final MethodHandle writeObjectForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class); + } + + private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl, + String methodName, + Class<?> streamClass) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + try { + Method meth = cl.getDeclaredMethod(methodName, streamClass); + int mods = meth.getModifiers(); + if (meth.getReturnType() != Void.TYPE || + Modifier.isStatic(mods) || + !Modifier.isPrivate(mods)) { + return null; + } + meth.setAccessible(true); + return MethodHandles.lookup().unreflect(meth); + } catch (NoSuchMethodException ex) { + return null; + } catch (IllegalAccessException ex1) { + throw new InternalError("Error", ex1); + } + } + + /** + * Returns a direct MethodHandle for the {@code readResolve} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code readResolve} method of the class or + * {@code null} if the class does not have a {@code readResolve} method + */ + public final MethodHandle readResolveForSerialization(Class<?> cl) { + return getReplaceResolveForSerialization(cl, "readResolve"); + } + + /** + * Returns a direct MethodHandle for the {@code writeReplace} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code writeReplace} method of the class or + * {@code null} if the class does not have a {@code writeReplace} method + */ + public final MethodHandle writeReplaceForSerialization(Class<?> cl) { + return getReplaceResolveForSerialization(cl, "writeReplace"); + } + + /** + * Returns a direct MethodHandle for the {@code writeReplace} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code writeReplace} method of the class or + * {@code null} if the class does not have a {@code writeReplace} method + */ + private MethodHandle getReplaceResolveForSerialization(Class<?> cl, + String methodName) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + Class<?> defCl = cl; + while (defCl != null) { + try { + Method m = defCl.getDeclaredMethod(methodName); + if (m.getReturnType() != Object.class) { + return null; + } + int mods = m.getModifiers(); + if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) { + return null; + } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) { + // fall through + } else if (Modifier.isPrivate(mods) && (cl != defCl)) { + return null; + } else if (!packageEquals(cl, defCl)) { + return null; + } + try { + // Normal return + m.setAccessible(true); + return MethodHandles.lookup().unreflect(m); + } catch (IllegalAccessException ex0) { + // setAccessible should prevent IAE + throw new InternalError("Error", ex0); + } + } catch (NoSuchMethodException ex) { + defCl = defCl.getSuperclass(); + } + } + return null; + } + + /** + * Returns true if the class has a static initializer. + * The presence of a static initializer is used to compute the serialVersionUID. + * @param cl a serializable classLook + * @return {@code true} if the class has a static initializer, + * otherwise {@code false} + */ + public final boolean hasStaticInitializerForSerialization(Class<?> cl) { + Method m = hasStaticInitializerMethod; + if (m == null) { + try { + m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", + new Class<?>[]{Class.class}); + m.setAccessible(true); + hasStaticInitializerMethod = m; + } catch (NoSuchMethodException ex) { + throw new InternalError("No such method hasStaticInitializer on " + + ObjectStreamClass.class, ex); + } + } + try { + return (Boolean) m.invoke(null, cl); + } catch (InvocationTargetException | IllegalAccessException ex) { + throw new InternalError("Exception invoking hasStaticInitializer", ex); + } + } + + /** + * Returns a new OptionalDataException with {@code eof} set to {@code true} + * or {@code false}. + * @param bool the value of {@code eof} in the created OptionalDataException + * @return a new OptionalDataException + */ + public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) { + try { + Constructor<OptionalDataException> boolCtor = + OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE); + boolCtor.setAccessible(true); + return boolCtor.newInstance(bool); + } catch (NoSuchMethodException | InstantiationException| + IllegalAccessException|InvocationTargetException ex) { + throw new InternalError("unable to create OptionalDataException", ex); + } + } + + //-------------------------------------------------------------------------- + // + // Internals only below this point + // + + static int inflationThreshold() { + return inflationThreshold; + } + + /** We have to defer full initialization of this class until after + the static initializer is run since java.lang.reflect.Method's + static initializer (more properly, that for + java.lang.reflect.AccessibleObject) causes this class's to be + run, before the system properties are set up. */ + private static void checkInitted() { + if (initted) return; + AccessController.doPrivileged( + new PrivilegedAction<Void>() { + public Void run() { + // Tests to ensure the system properties table is fully + // initialized. This is needed because reflection code is + // called very early in the initialization process (before + // command-line arguments have been parsed and therefore + // these user-settable properties installed.) We assume that + // if System.out is non-null then the System class has been + // fully initialized and that the bulk of the startup code + // has been run. + + if (System.out == null) { + // java.lang.System not yet fully initialized + return null; + } + + String val = System.getProperty("sun.reflect.noInflation"); + if (val != null && val.equals("true")) { + noInflation = true; + } + + val = System.getProperty("sun.reflect.inflationThreshold"); + if (val != null) { + try { + inflationThreshold = Integer.parseInt(val); + } catch (NumberFormatException e) { + throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e); + } + } + + initted = true; + return null; + } + }); + } + + private static LangReflectAccess langReflectAccess() { + if (langReflectAccess == null) { + // Call a static method to get class java.lang.reflect.Modifier + // initialized. Its static initializer will cause + // setLangReflectAccess() to be called from the context of the + // java.lang.reflect package. + Modifier.isPublic(Modifier.PUBLIC); + } + return langReflectAccess; + } + + /** + * Returns true if classes are defined in the classloader and same package, false + * otherwise. + * @param cl1 a class + * @param cl2 another class + * @returns true if the two classes are in the same classloader and package + */ + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) { + return cl1.getClassLoader() == cl2.getClassLoader() && + Objects.equals(cl1.getPackage(), cl2.getPackage()); + } + +} diff --git a/src/Java/sun/repackage/SecurityConstants.java b/src/Java/sun/repackage/SecurityConstants.java new file mode 100644 index 0000000000..da2829cac1 --- /dev/null +++ b/src/Java/sun/repackage/SecurityConstants.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003, 2019, 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.repackage; + +import java.net.NetPermission; +import java.net.SocketPermission; +import java.security.AllPermission; +import java.security.Permission; +import java.security.SecurityPermission; + +/** + * Permission constants and string constants used to create permissions + * used throughout the JDK. + */ +public final class SecurityConstants { + // Cannot create one of these + private SecurityConstants () { + } + + // Commonly used string constants for permission actions used by + // SecurityManager. Declare here for shortcut when checking permissions + // in FilePermission, SocketPermission, and PropertyPermission. + + public static final String FILE_DELETE_ACTION = "delete"; + public static final String FILE_EXECUTE_ACTION = "execute"; + public static final String FILE_READ_ACTION = "read"; + public static final String FILE_WRITE_ACTION = "write"; + public static final String FILE_READLINK_ACTION = "readlink"; + + public static final String SOCKET_RESOLVE_ACTION = "resolve"; + public static final String SOCKET_CONNECT_ACTION = "connect"; + public static final String SOCKET_LISTEN_ACTION = "listen"; + public static final String SOCKET_ACCEPT_ACTION = "accept"; + public static final String SOCKET_CONNECT_ACCEPT_ACTION = "connect,accept"; + + public static final String PROPERTY_RW_ACTION = "read,write"; + public static final String PROPERTY_READ_ACTION = "read"; + public static final String PROPERTY_WRITE_ACTION = "write"; + + // Permission constants used in the various checkPermission() calls in JDK. + + // java.lang.Class, java.lang.SecurityManager, java.lang.System, + // java.net.URLConnection, java.security.AllPermission, java.security.Policy, + // sun.security.provider.PolicyFile + public static final AllPermission ALL_PERMISSION = new AllPermission(); + + /** + * AWT Permissions used in the JDK. + */ + public static class AWT { + private AWT() { } + + /** + * The class name of the factory to create java.awt.AWTPermission objects. + */ + private static final String AWTFactory = "sun.awt.AWTPermissionFactory"; + + /** + * The PermissionFactory to create AWT permissions (or null if AWT is + * not present) + */ + private static final PermissionFactory<?> factory = permissionFactory(); + + private static PermissionFactory<?> permissionFactory() { + Class<?> c; + try { + c = Class.forName(AWTFactory, false, AWT.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // not available + return null; + } + // AWT present + try { + return (PermissionFactory<?>)c.newInstance(); + } catch (ReflectiveOperationException x) { + throw new InternalError(x); + } + } + + private static Permission newAWTPermission(String name) { + return (factory == null) ? null : factory.newPermission(name); + } + + // java.lang.SecurityManager + public static final Permission TOPLEVEL_WINDOW_PERMISSION = + newAWTPermission("showWindowWithoutWarningBanner"); + + // java.lang.SecurityManager + public static final Permission ACCESS_CLIPBOARD_PERMISSION = + newAWTPermission("accessClipboard"); + + // java.lang.SecurityManager + public static final Permission CHECK_AWT_EVENTQUEUE_PERMISSION = + newAWTPermission("accessEventQueue"); + + // java.awt.Dialog + public static final Permission TOOLKIT_MODALITY_PERMISSION = + newAWTPermission("toolkitModality"); + + // java.awt.Robot + public static final Permission READ_DISPLAY_PIXELS_PERMISSION = + newAWTPermission("readDisplayPixels"); + + // java.awt.Robot + public static final Permission CREATE_ROBOT_PERMISSION = + newAWTPermission("createRobot"); + + // java.awt.MouseInfo + public static final Permission WATCH_MOUSE_PERMISSION = + newAWTPermission("watchMousePointer"); + + // java.awt.Window + public static final Permission SET_WINDOW_ALWAYS_ON_TOP_PERMISSION = + newAWTPermission("setWindowAlwaysOnTop"); + + // java.awt.Toolkit + public static final Permission ALL_AWT_EVENTS_PERMISSION = + newAWTPermission("listenToAllAWTEvents"); + + // java.awt.SystemTray + public static final Permission ACCESS_SYSTEM_TRAY_PERMISSION = + newAWTPermission("accessSystemTray"); + } + + // java.net.URL + public static final NetPermission SPECIFY_HANDLER_PERMISSION = + new NetPermission("specifyStreamHandler"); + + // java.net.ProxySelector + public static final NetPermission SET_PROXYSELECTOR_PERMISSION = + new NetPermission("setProxySelector"); + + // java.net.ProxySelector + public static final NetPermission GET_PROXYSELECTOR_PERMISSION = + new NetPermission("getProxySelector"); + + // java.net.CookieHandler + public static final NetPermission SET_COOKIEHANDLER_PERMISSION = + new NetPermission("setCookieHandler"); + + // java.net.CookieHandler + public static final NetPermission GET_COOKIEHANDLER_PERMISSION = + new NetPermission("getCookieHandler"); + + // java.net.ResponseCache + public static final NetPermission SET_RESPONSECACHE_PERMISSION = + new NetPermission("setResponseCache"); + + // java.net.ResponseCache + public static final NetPermission GET_RESPONSECACHE_PERMISSION = + new NetPermission("getResponseCache"); + + // java.net.ServerSocket, java.net.Socket + public static final NetPermission SET_SOCKETIMPL_PERMISSION = + new NetPermission("setSocketImpl"); + + // java.lang.SecurityManager, sun.applet.AppletPanel, sun.misc.Launcher + public static final RuntimePermission CREATE_CLASSLOADER_PERMISSION = + new RuntimePermission("createClassLoader"); + + // java.lang.SecurityManager + public static final RuntimePermission CHECK_MEMBER_ACCESS_PERMISSION = + new RuntimePermission("accessDeclaredMembers"); + + // java.lang.SecurityManager, sun.applet.AppletSecurity + public static final RuntimePermission MODIFY_THREAD_PERMISSION = + new RuntimePermission("modifyThread"); + + // java.lang.SecurityManager, sun.applet.AppletSecurity + public static final RuntimePermission MODIFY_THREADGROUP_PERMISSION = + new RuntimePermission("modifyThreadGroup"); + + // java.lang.Class + public static final RuntimePermission GET_PD_PERMISSION = + new RuntimePermission("getProtectionDomain"); + + // java.lang.Class, java.lang.ClassLoader, java.lang.Thread + public static final RuntimePermission GET_CLASSLOADER_PERMISSION = + new RuntimePermission("getClassLoader"); + + // java.lang.Thread + public static final RuntimePermission STOP_THREAD_PERMISSION = + new RuntimePermission("stopThread"); + + // java.lang.Thread + public static final RuntimePermission GET_STACK_TRACE_PERMISSION = + new RuntimePermission("getStackTrace"); + + // java.security.AccessControlContext + public static final SecurityPermission CREATE_ACC_PERMISSION = + new SecurityPermission("createAccessControlContext"); + + // java.security.AccessControlContext + public static final SecurityPermission GET_COMBINER_PERMISSION = + new SecurityPermission("getDomainCombiner"); + + // java.security.Policy, java.security.ProtectionDomain + public static final SecurityPermission GET_POLICY_PERMISSION = + new SecurityPermission ("getPolicy"); + + // java.lang.SecurityManager + public static final SocketPermission LOCAL_LISTEN_PERMISSION = + new SocketPermission("localhost:0", SOCKET_LISTEN_ACTION); +} diff --git a/src/Java/sun/repackage/SerializationConstructorAccessorImpl.java b/src/Java/sun/repackage/SerializationConstructorAccessorImpl.java new file mode 100644 index 0000000000..c07a4f82a1 --- /dev/null +++ b/src/Java/sun/repackage/SerializationConstructorAccessorImpl.java @@ -0,0 +1,45 @@ +/* + * 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.repackage; + +/** <P> Java serialization (in java.io) expects to be able to + instantiate a class and invoke a no-arg constructor of that + class's first non-Serializable superclass. This is not a valid + operation according to the VM specification; one can not (for + classes A and B, where B is a subclass of A) write "new B; + invokespecial A()" without getting a verification error. </P> + + <P> In all other respects, the bytecode-based reflection framework + can be reused for this purpose. This marker class was originally + known to the VM and verification disabled for it and all + subclasses, but the bug fix for 4486457 necessitated disabling + verification for all of the dynamically-generated bytecodes + associated with reflection. This class has been left in place to + make future debugging easier. </P> */ + +abstract class SerializationConstructorAccessorImpl + extends ConstructorAccessorImpl { +} diff --git a/src/Java/sun/repackage/UTF8.java b/src/Java/sun/repackage/UTF8.java new file mode 100644 index 0000000000..0ff75f5f44 --- /dev/null +++ b/src/Java/sun/repackage/UTF8.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +/** It is necessary to use a "bootstrap" UTF-8 encoder for encoding + constant pool entries because the character set converters rely on + Class.newInstance(). */ + +class UTF8 { + // This encoder is not quite correct. It does not handle surrogate pairs. + static byte[] encode(String str) { + int len = str.length(); + byte[] res = new byte[utf8Length(str)]; + int utf8Idx = 0; + try { + for (int i = 0; i < len; i++) { + int c = str.charAt(i) & 0xFFFF; + if (c >= 0x0001 && c <= 0x007F) { + res[utf8Idx++] = (byte) c; + } else if (c == 0x0000 || + (c >= 0x0080 && c <= 0x07FF)) { + res[utf8Idx++] = (byte) (0xC0 + (c >> 6)); + res[utf8Idx++] = (byte) (0x80 + (c & 0x3F)); + } else { + res[utf8Idx++] = (byte) (0xE0 + (c >> 12)); + res[utf8Idx++] = (byte) (0x80 + ((c >> 6) & 0x3F)); + res[utf8Idx++] = (byte) (0x80 + (c & 0x3F)); + } + } + } catch (ArrayIndexOutOfBoundsException e) { + throw new InternalError + ("Bug in sun.reflect bootstrap UTF-8 encoder", e); + } + return res; + } + + private static int utf8Length(String str) { + int len = str.length(); + int utf8Len = 0; + for (int i = 0; i < len; i++) { + int c = str.charAt(i) & 0xFFFF; + if (c >= 0x0001 && c <= 0x007F) { + utf8Len += 1; + } else if (c == 0x0000 || + (c >= 0x0080 && c <= 0x07FF)) { + utf8Len += 2; + } else { + utf8Len += 3; + } + } + return utf8Len; + } +} diff --git a/src/Java/sun/repackage/Unsafe.java b/src/Java/sun/repackage/Unsafe.java new file mode 100644 index 0000000000..38b00b54df --- /dev/null +++ b/src/Java/sun/repackage/Unsafe.java @@ -0,0 +1,1146 @@ +/* + * Copyright (c) 2000, 2013, 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.repackage; + +import java.security.*; + +import sun.repackage.CallerSensitive; +import sun.repackage.Reflection; + +import java.lang.reflect.*; + + +/** + * A collection of methods for performing low-level, unsafe operations. + * Although the class and all methods are public, use of this class is + * limited because only trusted code can obtain instances of it. + * + * @author John R. Rose + * @see #getUnsafe + */ + +public final class Unsafe { + + private static native void registerNatives(); + static { + registerNatives(); + sun.repackage.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); + } + + private Unsafe() {} + + private static final Unsafe theUnsafe = new Unsafe(); + + /** + * Provides the caller with the capability of performing unsafe + * operations. + * + * <p> The returned <code>Unsafe</code> object should be carefully guarded + * by the caller, since it can be used to read and write data at arbitrary + * memory addresses. It must never be passed to untrusted code. + * + * <p> Most methods in this class are very low-level, and correspond to a + * small number of hardware instructions (on typical machines). Compilers + * are encouraged to optimize these methods accordingly. + * + * <p> Here is a suggested idiom for using unsafe operations: + * + * <blockquote><pre> + * class MyTrustedClass { + * private static final Unsafe unsafe = Unsafe.getUnsafe(); + * ... + * private long myCountAddress = ...; + * public int getCount() { return unsafe.getByte(myCountAddress); } + * } + * </pre></blockquote> + * + * (It may assist compilers to make the local variable be + * <code>final</code>.) + * + * @exception SecurityException if a security manager exists and its + * <code>checkPropertiesAccess</code> method doesn't allow + * access to the system properties. + */ + @CallerSensitive + public static Unsafe getUnsafe() { + Class<?> caller = Reflection.getCallerClass(); + if (!Reflection.isSystemDomainLoader(caller.getClassLoader())) + throw new SecurityException("Unsafe"); + return theUnsafe; + } + + /// peek and poke operations + /// (compilers should optimize these to memory ops) + + // These work on object fields in the Java heap. + // They will not work on elements of packed arrays. + + /** + * Fetches a value from a given Java variable. + * More specifically, fetches a field or array element within the given + * object <code>o</code> at the given offset, or (if <code>o</code> is + * null) from the memory address whose numerical value is the given + * offset. + * <p> + * The results are undefined unless one of the following cases is true: + * <ul> + * <li>The offset was obtained from {@link #objectFieldOffset} on + * the {@link java.lang.reflect.Field} of some Java field and the object + * referred to by <code>o</code> is of a class compatible with that + * field's class. + * + * <li>The offset and object reference <code>o</code> (either null or + * non-null) were both obtained via {@link #staticFieldOffset} + * and {@link #staticFieldBase} (respectively) from the + * reflective {@link Field} representation of some Java field. + * + * <li>The object referred to by <code>o</code> is an array, and the offset + * is an integer of the form <code>B+N*S</code>, where <code>N</code> is + * a valid index into the array, and <code>B</code> and <code>S</code> are + * the values obtained by {@link #arrayBaseOffset} and {@link + * #arrayIndexScale} (respectively) from the array's class. The value + * referred to is the <code>N</code><em>th</em> element of the array. + * + * </ul> + * <p> + * If one of the above cases is true, the call references a specific Java + * variable (field or array element). However, the results are undefined + * if that variable is not in fact of the type returned by this method. + * <p> + * This method refers to a variable by means of two parameters, and so + * it provides (in effect) a <em>double-register</em> addressing mode + * for Java variables. When the object reference is null, this method + * uses its offset as an absolute address. This is similar in operation + * to methods such as {@link #getInt(long)}, which provide (in effect) a + * <em>single-register</em> addressing mode for non-Java variables. + * However, because Java variables may have a different layout in memory + * from non-Java variables, programmers should not assume that these + * two addressing modes are ever equivalent. Also, programmers should + * remember that offsets from the double-register addressing mode cannot + * be portably confused with longs used in the single-register addressing + * mode. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @return the value fetched from the indicated Java variable + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + public native int getInt(Object o, long offset); + + /** + * Stores a value into a given Java variable. + * <p> + * The first two parameters are interpreted exactly as with + * {@link #getInt(Object, long)} to refer to a specific + * Java variable (field or array element). The given value + * is stored into that variable. + * <p> + * The variable must be of the same type as the method + * parameter <code>x</code>. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @param x the value to store into the indicated Java variable + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + public native void putInt(Object o, long offset, int x); + + /** + * Fetches a reference value from a given Java variable. + * @see #getInt(Object, long) + */ + public native Object getObject(Object o, long offset); + + /** + * Stores a reference value into a given Java variable. + * <p> + * Unless the reference <code>x</code> being stored is either null + * or matches the field type, the results are undefined. + * If the reference <code>o</code> is non-null, car marks or + * other store barriers for that object (if the VM requires them) + * are updated. + * @see #putInt(Object, int, int) + */ + public native void putObject(Object o, long offset, Object x); + + /** @see #getInt(Object, long) */ + public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ + public native byte getByte(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ + public native short getShort(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ + public native char getChar(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ + public native long getLong(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ + public native float getFloat(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ + public native double getDouble(Object o, long offset); + /** @see #putInt(Object, int, int) */ + public native void putDouble(Object o, long offset, double x); + + /** + * This method, like all others with 32-bit offsets, was native + * in a previous release but is now a wrapper which simply casts + * the offset to a long value. It provides backward compatibility + * with bytecodes compiled against 1.4. + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public int getInt(Object o, int offset) { + return getInt(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putInt(Object o, int offset, int x) { + putInt(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public Object getObject(Object o, int offset) { + return getObject(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putObject(Object o, int offset, Object x) { + putObject(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public boolean getBoolean(Object o, int offset) { + return getBoolean(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putBoolean(Object o, int offset, boolean x) { + putBoolean(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public byte getByte(Object o, int offset) { + return getByte(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putByte(Object o, int offset, byte x) { + putByte(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public short getShort(Object o, int offset) { + return getShort(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putShort(Object o, int offset, short x) { + putShort(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public char getChar(Object o, int offset) { + return getChar(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putChar(Object o, int offset, char x) { + putChar(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public long getLong(Object o, int offset) { + return getLong(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putLong(Object o, int offset, long x) { + putLong(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public float getFloat(Object o, int offset) { + return getFloat(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putFloat(Object o, int offset, float x) { + putFloat(o, (long)offset, x); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public double getDouble(Object o, int offset) { + return getDouble(o, (long)offset); + } + + /** + * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long. + * See {@link #staticFieldOffset}. + */ + @Deprecated + public void putDouble(Object o, int offset, double x) { + putDouble(o, (long)offset, x); + } + + // These work on values in the C heap. + + /** + * Fetches a value from a given memory address. If the address is zero, or + * does not point into a block obtained from {@link #allocateMemory}, the + * results are undefined. + * + * @see #allocateMemory + */ + public native byte getByte(long address); + + /** + * Stores a value into a given memory address. If the address is zero, or + * does not point into a block obtained from {@link #allocateMemory}, the + * results are undefined. + * + * @see #getByte(long) + */ + public native void putByte(long address, byte x); + + /** @see #getByte(long) */ + public native short getShort(long address); + /** @see #putByte(long, byte) */ + public native void putShort(long address, short x); + /** @see #getByte(long) */ + public native char getChar(long address); + /** @see #putByte(long, byte) */ + public native void putChar(long address, char x); + /** @see #getByte(long) */ + public native int getInt(long address); + /** @see #putByte(long, byte) */ + public native void putInt(long address, int x); + /** @see #getByte(long) */ + public native long getLong(long address); + /** @see #putByte(long, byte) */ + public native void putLong(long address, long x); + /** @see #getByte(long) */ + public native float getFloat(long address); + /** @see #putByte(long, byte) */ + public native void putFloat(long address, float x); + /** @see #getByte(long) */ + public native double getDouble(long address); + /** @see #putByte(long, byte) */ + public native void putDouble(long address, double x); + + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p> If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address maybe determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + */ + public native long getAddress(long address); + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p> The number of bytes actually written at the target address maybe + * determined by consulting {@link #addressSize}. + * + * @see #getAddress(long) + */ + public native void putAddress(long address, long x); + + /// wrappers for malloc, realloc, free: + + /** + * Allocates a new block of native memory, of the given size in bytes. The + * contents of the memory are uninitialized; they will generally be + * garbage. The resulting native pointer will never be zero, and will be + * aligned for all value types. Dispose of this memory by calling {@link + * #freeMemory}, or resize it with {@link #reallocateMemory}. + * + * @throws IllegalArgumentException if the size is negative or too large + * for the native size_t type + * + * @throws OutOfMemoryError if the allocation is refused by the system + * + * @see #getByte(long) + * @see #putByte(long, byte) + */ + public native long allocateMemory(long bytes); + + /** + * Resizes a new block of native memory, to the given size in bytes. The + * contents of the new block past the size of the old block are + * uninitialized; they will generally be garbage. The resulting native + * pointer will be zero if and only if the requested size is zero. The + * resulting native pointer will be aligned for all value types. Dispose + * of this memory by calling {@link #freeMemory}, or resize it with {@link + * #reallocateMemory}. The address passed to this method may be null, in + * which case an allocation will be performed. + * + * @throws IllegalArgumentException if the size is negative or too large + * for the native size_t type + * + * @throws OutOfMemoryError if the allocation is refused by the system + * + * @see #allocateMemory + */ + public native long reallocateMemory(long address, long bytes); + + /** + * Sets all bytes in a given block of memory to a fixed value + * (usually zero). + * + * <p>This method determines a block's base address by means of two parameters, + * and so it provides (in effect) a <em>double-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * <p>The stores are in coherent (atomic) units of a size determined + * by the address and length parameters. If the effective address and + * length are all even modulo 8, the stores take place in 'long' units. + * If the effective address and length are (resp.) even modulo 4 or 2, + * the stores take place in units of 'int' or 'short'. + * + * @since 1.7 + */ + public native void setMemory(Object o, long offset, long bytes, byte value); + + /** + * Sets all bytes in a given block of memory to a fixed value + * (usually zero). This provides a <em>single-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. + * + * <p>Equivalent to <code>setMemory(null, address, bytes, value)</code>. + */ + public void setMemory(long address, long bytes, byte value) { + setMemory(null, address, bytes, value); + } + + /** + * Sets all bytes in a given block of memory to a copy of another + * block. + * + * <p>This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a <em>double-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * <p>The transfers are in coherent (atomic) units of a size determined + * by the address and length parameters. If the effective addresses and + * length are all even modulo 8, the transfer takes place in 'long' units. + * If the effective addresses and length are (resp.) even modulo 4 or 2, + * the transfer takes place in units of 'int' or 'short'. + * + * @since 1.7 + */ + public native void copyMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes); + /** + * Sets all bytes in a given block of memory to a copy of another + * block. This provides a <em>single-register</em> addressing mode, + * as discussed in {@link #getInt(Object,long)}. + * + * Equivalent to <code>copyMemory(null, srcAddress, null, destAddress, bytes)</code>. + */ + public void copyMemory(long srcAddress, long destAddress, long bytes) { + copyMemory(null, srcAddress, null, destAddress, bytes); + } + + /** + * Disposes of a block of native memory, as obtained from {@link + * #allocateMemory} or {@link #reallocateMemory}. The address passed to + * this method may be null, in which case no action is taken. + * + * @see #allocateMemory + */ + public native void freeMemory(long address); + + /// random queries + + /** + * This constant differs from all results that will ever be returned from + * {@link #staticFieldOffset}, {@link #objectFieldOffset}, + * or {@link #arrayBaseOffset}. + */ + public static final int INVALID_FIELD_OFFSET = -1; + + /** + * Returns the offset of a field, truncated to 32 bits. + * This method is implemented as follows: + * <blockquote><pre> + * public int fieldOffset(Field f) { + * if (Modifier.isStatic(f.getModifiers())) + * return (int) staticFieldOffset(f); + * else + * return (int) objectFieldOffset(f); + * } + * </pre></blockquote> + * @deprecated As of 1.4.1, use {@link #staticFieldOffset} for static + * fields and {@link #objectFieldOffset} for non-static fields. + */ + @Deprecated + public int fieldOffset(Field f) { + if (Modifier.isStatic(f.getModifiers())) + return (int) staticFieldOffset(f); + else + return (int) objectFieldOffset(f); + } + + /** + * Returns the base address for accessing some static field + * in the given class. This method is implemented as follows: + * <blockquote><pre> + * public Object staticFieldBase(Class c) { + * Field[] fields = c.getDeclaredFields(); + * for (int i = 0; i < fields.length; i++) { + * if (Modifier.isStatic(fields[i].getModifiers())) { + * return staticFieldBase(fields[i]); + * } + * } + * return null; + * } + * </pre></blockquote> + * @deprecated As of 1.4.1, use {@link #staticFieldBase(Field)} + * to obtain the base pertaining to a specific {@link Field}. + * This method works only for JVMs which store all statics + * for a given class in one place. + */ + @Deprecated + public Object staticFieldBase(Class<?> c) { + Field[] fields = c.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + if (Modifier.isStatic(fields[i].getModifiers())) { + return staticFieldBase(fields[i]); + } + } + return null; + } + + /** + * Report the location of a given field in the storage allocation of its + * class. Do not expect to perform any sort of arithmetic on this offset; + * it is just a cookie which is passed to the unsafe heap memory accessors. + * + * <p>Any given field will always have the same offset and base, and no + * two distinct fields of the same class will ever have the same offset + * and base. + * + * <p>As of 1.4.1, offsets for fields are represented as long values, + * although the Sun JVM does not use the most significant 32 bits. + * However, JVM implementations which store static fields at absolute + * addresses can use long offsets and null base pointers to express + * the field locations in a form usable by {@link #getInt(Object,long)}. + * Therefore, code which will be ported to such JVMs on 64-bit platforms + * must preserve all bits of static field offsets. + * @see #getInt(Object, long) + */ + public native long staticFieldOffset(Field f); + + /** + * Report the location of a given static field, in conjunction with {@link + * #staticFieldBase}. + * <p>Do not expect to perform any sort of arithmetic on this offset; + * it is just a cookie which is passed to the unsafe heap memory accessors. + * + * <p>Any given field will always have the same offset, and no two distinct + * fields of the same class will ever have the same offset. + * + * <p>As of 1.4.1, offsets for fields are represented as long values, + * although the Sun JVM does not use the most significant 32 bits. + * It is hard to imagine a JVM technology which needs more than + * a few bits to encode an offset within a non-array object, + * However, for consistency with other methods in this class, + * this method reports its result as a long value. + * @see #getInt(Object, long) + */ + public native long objectFieldOffset(Field f); + + /** + * Report the location of a given static field, in conjunction with {@link + * #staticFieldOffset}. + * <p>Fetch the base "Object", if any, with which static fields of the + * given class can be accessed via methods like {@link #getInt(Object, + * long)}. This value may be null. This value may refer to an object + * which is a "cookie", not guaranteed to be a real Object, and it should + * not be used in any way except as argument to the get and put routines in + * this class. + */ + public native Object staticFieldBase(Field f); + + /** + * Detect if the given class may need to be initialized. This is often + * needed in conjunction with obtaining the static field base of a + * class. + * @return false only if a call to {@code ensureClassInitialized} would have no effect + */ + public native boolean shouldBeInitialized(Class<?> c); + + /** + * Ensure the given class has been initialized. This is often + * needed in conjunction with obtaining the static field base of a + * class. + */ + public native void ensureClassInitialized(Class<?> c); + + /** + * Report the offset of the first element in the storage allocation of a + * given array class. If {@link #arrayIndexScale} returns a non-zero value + * for the same class, you may use that scale factor, together with this + * base offset, to form new offsets to access elements of arrays of the + * given class. + * + * @see #getInt(Object, long) + * @see #putInt(Object, long, int) + */ + public native int arrayBaseOffset(Class<?> arrayClass); + + /** The value of {@code arrayBaseOffset(boolean[].class)} */ + public static final int ARRAY_BOOLEAN_BASE_OFFSET + = theUnsafe.arrayBaseOffset(boolean[].class); + + /** The value of {@code arrayBaseOffset(byte[].class)} */ + public static final int ARRAY_BYTE_BASE_OFFSET + = theUnsafe.arrayBaseOffset(byte[].class); + + /** The value of {@code arrayBaseOffset(short[].class)} */ + public static final int ARRAY_SHORT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(short[].class); + + /** The value of {@code arrayBaseOffset(char[].class)} */ + public static final int ARRAY_CHAR_BASE_OFFSET + = theUnsafe.arrayBaseOffset(char[].class); + + /** The value of {@code arrayBaseOffset(int[].class)} */ + public static final int ARRAY_INT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(int[].class); + + /** The value of {@code arrayBaseOffset(long[].class)} */ + public static final int ARRAY_LONG_BASE_OFFSET + = theUnsafe.arrayBaseOffset(long[].class); + + /** The value of {@code arrayBaseOffset(float[].class)} */ + public static final int ARRAY_FLOAT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(float[].class); + + /** The value of {@code arrayBaseOffset(double[].class)} */ + public static final int ARRAY_DOUBLE_BASE_OFFSET + = theUnsafe.arrayBaseOffset(double[].class); + + /** The value of {@code arrayBaseOffset(Object[].class)} */ + public static final int ARRAY_OBJECT_BASE_OFFSET + = theUnsafe.arrayBaseOffset(Object[].class); + + /** + * Report the scale factor for addressing elements in the storage + * allocation of a given array class. However, arrays of "narrow" types + * will generally not work properly with accessors like {@link + * #getByte(Object, int)}, so the scale factor for such classes is reported + * as zero. + * + * @see #arrayBaseOffset + * @see #getInt(Object, long) + * @see #putInt(Object, long, int) + */ + public native int arrayIndexScale(Class<?> arrayClass); + + /** The value of {@code arrayIndexScale(boolean[].class)} */ + public static final int ARRAY_BOOLEAN_INDEX_SCALE + = theUnsafe.arrayIndexScale(boolean[].class); + + /** The value of {@code arrayIndexScale(byte[].class)} */ + public static final int ARRAY_BYTE_INDEX_SCALE + = theUnsafe.arrayIndexScale(byte[].class); + + /** The value of {@code arrayIndexScale(short[].class)} */ + public static final int ARRAY_SHORT_INDEX_SCALE + = theUnsafe.arrayIndexScale(short[].class); + + /** The value of {@code arrayIndexScale(char[].class)} */ + public static final int ARRAY_CHAR_INDEX_SCALE + = theUnsafe.arrayIndexScale(char[].class); + + /** The value of {@code arrayIndexScale(int[].class)} */ + public static final int ARRAY_INT_INDEX_SCALE + = theUnsafe.arrayIndexScale(int[].class); + + /** The value of {@code arrayIndexScale(long[].class)} */ + public static final int ARRAY_LONG_INDEX_SCALE + = theUnsafe.arrayIndexScale(long[].class); + + /** The value of {@code arrayIndexScale(float[].class)} */ + public static final int ARRAY_FLOAT_INDEX_SCALE + = theUnsafe.arrayIndexScale(float[].class); + + /** The value of {@code arrayIndexScale(double[].class)} */ + public static final int ARRAY_DOUBLE_INDEX_SCALE + = theUnsafe.arrayIndexScale(double[].class); + + /** The value of {@code arrayIndexScale(Object[].class)} */ + public static final int ARRAY_OBJECT_INDEX_SCALE + = theUnsafe.arrayIndexScale(Object[].class); + + /** + * Report the size in bytes of a native pointer, as stored via {@link + * #putAddress}. This value will be either 4 or 8. Note that the sizes of + * other primitive types (as stored in native memory blocks) is determined + * fully by their information content. + */ + public native int addressSize(); + + /** The value of {@code addressSize()} */ + public static final int ADDRESS_SIZE = theUnsafe.addressSize(); + + /** + * Report the size in bytes of a native memory page (whatever that is). + * This value will always be a power of two. + */ + public native int pageSize(); + + + /// random trusted operations from JNI: + + /** + * Tell the VM to define a class, without security checks. By default, the + * class loader and protection domain come from the caller's class. + */ + public native Class<?> defineClass(String name, byte[] b, int off, int len, + ClassLoader loader, + ProtectionDomain protectionDomain); + + /** + * Define a class but do not make it known to the class loader or system dictionary. + * <p> + * For each CP entry, the corresponding CP patch must either be null or have + * the a format that matches its tag: + * <ul> + * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang + * <li>Utf8: a string (must have suitable syntax if used as signature or name) + * <li>Class: any java.lang.Class object + * <li>String: any object (not just a java.lang.String) + * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments + * </ul> + * @params hostClass context for linkage, access control, protection domain, and class loader + * @params data bytes of a class file + * @params cpPatches where non-null entries exist, they replace corresponding CP entries in data + */ + public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches); + + + /** Allocate an instance but do not run any constructor. + Initializes the class if it has not yet been. */ + public native Object allocateInstance(Class<?> cls) + throws InstantiationException; + + /** Lock the object. It must get unlocked via {@link #monitorExit}. */ + @Deprecated + public native void monitorEnter(Object o); + + /** + * Unlock the object. It must have been locked via {@link + * #monitorEnter}. + */ + @Deprecated + public native void monitorExit(Object o); + + /** + * Tries to lock the object. Returns true or false to indicate + * whether the lock succeeded. If it did, the object must be + * unlocked via {@link #monitorExit}. + */ + @Deprecated + public native boolean tryMonitorEnter(Object o); + + /** Throw the exception without telling the verifier. */ + public native void throwException(Throwable ee); + + + /** + * Atomically update Java variable to <tt>x</tt> if it is currently + * holding <tt>expected</tt>. + * @return <tt>true</tt> if successful + */ + public final native boolean compareAndSwapObject(Object o, long offset, + Object expected, + Object x); + + /** + * Atomically update Java variable to <tt>x</tt> if it is currently + * holding <tt>expected</tt>. + * @return <tt>true</tt> if successful + */ + public final native boolean compareAndSwapInt(Object o, long offset, + int expected, + int x); + + /** + * Atomically update Java variable to <tt>x</tt> if it is currently + * holding <tt>expected</tt>. + * @return <tt>true</tt> if successful + */ + public final native boolean compareAndSwapLong(Object o, long offset, + long expected, + long x); + + /** + * Fetches a reference value from a given Java variable, with volatile + * load semantics. Otherwise identical to {@link #getObject(Object, long)} + */ + public native Object getObjectVolatile(Object o, long offset); + + /** + * Stores a reference value into a given Java variable, with + * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)} + */ + public native void putObjectVolatile(Object o, long offset, Object x); + + /** Volatile version of {@link #getInt(Object, long)} */ + public native int getIntVolatile(Object o, long offset); + + /** Volatile version of {@link #putInt(Object, long, int)} */ + public native void putIntVolatile(Object o, long offset, int x); + + /** Volatile version of {@link #getBoolean(Object, long)} */ + public native boolean getBooleanVolatile(Object o, long offset); + + /** Volatile version of {@link #putBoolean(Object, long, boolean)} */ + public native void putBooleanVolatile(Object o, long offset, boolean x); + + /** Volatile version of {@link #getByte(Object, long)} */ + public native byte getByteVolatile(Object o, long offset); + + /** Volatile version of {@link #putByte(Object, long, byte)} */ + public native void putByteVolatile(Object o, long offset, byte x); + + /** Volatile version of {@link #getShort(Object, long)} */ + public native short getShortVolatile(Object o, long offset); + + /** Volatile version of {@link #putShort(Object, long, short)} */ + public native void putShortVolatile(Object o, long offset, short x); + + /** Volatile version of {@link #getChar(Object, long)} */ + public native char getCharVolatile(Object o, long offset); + + /** Volatile version of {@link #putChar(Object, long, char)} */ + public native void putCharVolatile(Object o, long offset, char x); + + /** Volatile version of {@link #getLong(Object, long)} */ + public native long getLongVolatile(Object o, long offset); + + /** Volatile version of {@link #putLong(Object, long, long)} */ + public native void putLongVolatile(Object o, long offset, long x); + + /** Volatile version of {@link #getFloat(Object, long)} */ + public native float getFloatVolatile(Object o, long offset); + + /** Volatile version of {@link #putFloat(Object, long, float)} */ + public native void putFloatVolatile(Object o, long offset, float x); + + /** Volatile version of {@link #getDouble(Object, long)} */ + public native double getDoubleVolatile(Object o, long offset); + + /** Volatile version of {@link #putDouble(Object, long, double)} */ + public native void putDoubleVolatile(Object o, long offset, double x); + + /** + * Version of {@link #putObjectVolatile(Object, long, Object)} + * that does not guarantee immediate visibility of the store to + * other threads. This method is generally only useful if the + * underlying field is a Java volatile (or if an array cell, one + * that is otherwise only accessed using volatile accesses). + */ + public native void putOrderedObject(Object o, long offset, Object x); + + /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */ + public native void putOrderedInt(Object o, long offset, int x); + + /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */ + public native void putOrderedLong(Object o, long offset, long x); + + /** + * Unblock the given thread blocked on <tt>park</tt>, or, if it is + * not blocked, cause the subsequent call to <tt>park</tt> not to + * block. Note: this operation is "unsafe" solely because the + * caller must somehow ensure that the thread has not been + * destroyed. Nothing special is usually required to ensure this + * when called from Java (in which there will ordinarily be a live + * reference to the thread) but this is not nearly-automatically + * so when calling from native code. + * @param thread the thread to unpark. + * + */ + public native void unpark(Object thread); + + /** + * Block current thread, returning when a balancing + * <tt>unpark</tt> occurs, or a balancing <tt>unpark</tt> has + * already occurred, or the thread is interrupted, or, if not + * absolute and time is not zero, the given time nanoseconds have + * elapsed, or if absolute, the given deadline in milliseconds + * since Epoch has passed, or spuriously (i.e., returning for no + * "reason"). Note: This operation is in the Unsafe class only + * because <tt>unpark</tt> is, so it would be strange to place it + * elsewhere. + */ + public native void park(boolean isAbsolute, long time); + + /** + * Gets the load average in the system run queue assigned + * to the available processors averaged over various periods of time. + * This method retrieves the given <tt>nelem</tt> samples and + * assigns to the elements of the given <tt>loadavg</tt> array. + * The system imposes a maximum of 3 samples, representing + * averages over the last 1, 5, and 15 minutes, respectively. + * + * @params loadavg an array of double of size nelems + * @params nelems the number of samples to be retrieved and + * must be 1 to 3. + * + * @return the number of samples actually retrieved; or -1 + * if the load average is unobtainable. + */ + public native int getLoadAverage(double[] loadavg, int nelems); + + // The following contain CAS-based Java implementations used on + // platforms not supporting native instructions + + /** + * Atomically adds the given value to the current value of a field + * or array element within the given object <code>o</code> + * at the given <code>offset</code>. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param delta the value to add + * @return the previous value + * @since 1.8 + */ + public final int getAndAddInt(Object o, long offset, int delta) { + int v; + do { + v = getIntVolatile(o, offset); + } while (!compareAndSwapInt(o, offset, v, v + delta)); + return v; + } + + /** + * Atomically adds the given value to the current value of a field + * or array element within the given object <code>o</code> + * at the given <code>offset</code>. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param delta the value to add + * @return the previous value + * @since 1.8 + */ + public final long getAndAddLong(Object o, long offset, long delta) { + long v; + do { + v = getLongVolatile(o, offset); + } while (!compareAndSwapLong(o, offset, v, v + delta)); + return v; + } + + /** + * Atomically exchanges the given value with the current value of + * a field or array element within the given object <code>o</code> + * at the given <code>offset</code>. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + public final int getAndSetInt(Object o, long offset, int newValue) { + int v; + do { + v = getIntVolatile(o, offset); + } while (!compareAndSwapInt(o, offset, v, newValue)); + return v; + } + + /** + * Atomically exchanges the given value with the current value of + * a field or array element within the given object <code>o</code> + * at the given <code>offset</code>. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + public final long getAndSetLong(Object o, long offset, long newValue) { + long v; + do { + v = getLongVolatile(o, offset); + } while (!compareAndSwapLong(o, offset, v, newValue)); + return v; + } + + /** + * Atomically exchanges the given reference value with the current + * reference value of a field or array element within the given + * object <code>o</code> at the given <code>offset</code>. + * + * @param o object/array to update the field/element in + * @param offset field/element offset + * @param newValue new value + * @return the previous value + * @since 1.8 + */ + public final Object getAndSetObject(Object o, long offset, Object newValue) { + Object v; + do { + v = getObjectVolatile(o, offset); + } while (!compareAndSwapObject(o, offset, v, newValue)); + return v; + } + + + /** + * Ensures lack of reordering of loads before the fence + * with loads or stores after the fence. + * @since 1.8 + */ + public native void loadFence(); + + /** + * Ensures lack of reordering of stores before the fence + * with loads or stores after the fence. + * @since 1.8 + */ + public native void storeFence(); + + /** + * Ensures lack of reordering of loads or stores before the fence + * with loads or stores after the fence. + * @since 1.8 + */ + public native void fullFence(); + + /** + * Throws IllegalAccessError; for use by the VM. + * @since 1.8 + */ + private static void throwIllegalAccessError() { + throw new IllegalAccessError(); + } + +} diff --git a/src/Java/sun/repackage/UnsafeFieldAccessorFactory.java b/src/Java/sun/repackage/UnsafeFieldAccessorFactory.java new file mode 100644 index 0000000000..d52b36c42c --- /dev/null +++ b/src/Java/sun/repackage/UnsafeFieldAccessorFactory.java @@ -0,0 +1,4446 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +class UnsafeFieldAccessorFactory { + static FieldAccessor newFieldAccessor(Field field, boolean override) { + Class<?> type = field.getType(); + boolean isStatic = Modifier.isStatic(field.getModifiers()); + boolean isFinal = Modifier.isFinal(field.getModifiers()); + boolean isVolatile = Modifier.isVolatile(field.getModifiers()); + boolean isQualified = isFinal || isVolatile; + boolean isReadOnly = isFinal && (isStatic || !override); + if (isStatic) { + // This code path does not guarantee that the field's + // declaring class has been initialized, but it must be + // before performing reflective operations. + UnsafeFieldAccessorImpl.unsafe.ensureClassInitialized(field.getDeclaringClass()); + + if (!isQualified) { + if (type == Boolean.TYPE) { + return new UnsafeStaticBooleanFieldAccessorImpl(field); + } else if (type == Byte.TYPE) { + return new UnsafeStaticByteFieldAccessorImpl(field); + } else if (type == Short.TYPE) { + return new UnsafeStaticShortFieldAccessorImpl(field); + } else if (type == Character.TYPE) { + return new UnsafeStaticCharacterFieldAccessorImpl(field); + } else if (type == Integer.TYPE) { + return new UnsafeStaticIntegerFieldAccessorImpl(field); + } else if (type == Long.TYPE) { + return new UnsafeStaticLongFieldAccessorImpl(field); + } else if (type == Float.TYPE) { + return new UnsafeStaticFloatFieldAccessorImpl(field); + } else if (type == Double.TYPE) { + return new UnsafeStaticDoubleFieldAccessorImpl(field); + } else { + return new UnsafeStaticObjectFieldAccessorImpl(field); + } + } else { + if (type == Boolean.TYPE) { + return new UnsafeQualifiedStaticBooleanFieldAccessorImpl(field, isReadOnly); + } else if (type == Byte.TYPE) { + return new UnsafeQualifiedStaticByteFieldAccessorImpl(field, isReadOnly); + } else if (type == Short.TYPE) { + return new UnsafeQualifiedStaticShortFieldAccessorImpl(field, isReadOnly); + } else if (type == Character.TYPE) { + return new UnsafeQualifiedStaticCharacterFieldAccessorImpl(field, isReadOnly); + } else if (type == Integer.TYPE) { + return new UnsafeQualifiedStaticIntegerFieldAccessorImpl(field, isReadOnly); + } else if (type == Long.TYPE) { + return new UnsafeQualifiedStaticLongFieldAccessorImpl(field, isReadOnly); + } else if (type == Float.TYPE) { + return new UnsafeQualifiedStaticFloatFieldAccessorImpl(field, isReadOnly); + } else if (type == Double.TYPE) { + return new UnsafeQualifiedStaticDoubleFieldAccessorImpl(field, isReadOnly); + } else { + return new UnsafeQualifiedStaticObjectFieldAccessorImpl(field, isReadOnly); + } + } + } else { + if (!isQualified) { + if (type == Boolean.TYPE) { + return new UnsafeBooleanFieldAccessorImpl(field); + } else if (type == Byte.TYPE) { + return new UnsafeByteFieldAccessorImpl(field); + } else if (type == Short.TYPE) { + return new UnsafeShortFieldAccessorImpl(field); + } else if (type == Character.TYPE) { + return new UnsafeCharacterFieldAccessorImpl(field); + } else if (type == Integer.TYPE) { + return new UnsafeIntegerFieldAccessorImpl(field); + } else if (type == Long.TYPE) { + return new UnsafeLongFieldAccessorImpl(field); + } else if (type == Float.TYPE) { + return new UnsafeFloatFieldAccessorImpl(field); + } else if (type == Double.TYPE) { + return new UnsafeDoubleFieldAccessorImpl(field); + } else { + return new UnsafeObjectFieldAccessorImpl(field); + } + } else { + if (type == Boolean.TYPE) { + return new UnsafeQualifiedBooleanFieldAccessorImpl(field, isReadOnly); + } else if (type == Byte.TYPE) { + return new UnsafeQualifiedByteFieldAccessorImpl(field, isReadOnly); + } else if (type == Short.TYPE) { + return new UnsafeQualifiedShortFieldAccessorImpl(field, isReadOnly); + } else if (type == Character.TYPE) { + return new UnsafeQualifiedCharacterFieldAccessorImpl(field, isReadOnly); + } else if (type == Integer.TYPE) { + return new UnsafeQualifiedIntegerFieldAccessorImpl(field, isReadOnly); + } else if (type == Long.TYPE) { + return new UnsafeQualifiedLongFieldAccessorImpl(field, isReadOnly); + } else if (type == Float.TYPE) { + return new UnsafeQualifiedFloatFieldAccessorImpl(field, isReadOnly); + } else if (type == Double.TYPE) { + return new UnsafeQualifiedDoubleFieldAccessorImpl(field, isReadOnly); + } else { + return new UnsafeQualifiedObjectFieldAccessorImpl(field, isReadOnly); + } + } + } + } + + public static abstract class UnsafeStaticFieldAccessorImpl extends UnsafeFieldAccessorImpl { + static { + Reflection.registerFieldsToFilter(UnsafeStaticFieldAccessorImpl.class, + new String[] { "base" }); + } + + protected final Object base; // base + + UnsafeStaticFieldAccessorImpl(Field field) { + super(field); + base = unsafe.staticFieldBase(field); + } + } + + + public static class UnsafeStaticBooleanFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticBooleanFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Boolean(getBoolean(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + return unsafe.getBoolean(base, fieldOffset); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Boolean) { + unsafe.putBoolean(base, fieldOffset, ((Boolean) value).booleanValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(z); + } + unsafe.putBoolean(base, fieldOffset, z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticByteFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticByteFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Byte(getByte(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + return unsafe.getByte(base, fieldOffset); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putByte(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(b); + } + unsafe.putByte(base, fieldOffset, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticCharacterFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticCharacterFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Character(getChar(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + return unsafe.getChar(base, fieldOffset); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Character) { + unsafe.putChar(base, fieldOffset, ((Character) value).charValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(c); + } + unsafe.putChar(base, fieldOffset, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticDoubleFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticDoubleFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Double(getDouble(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return unsafe.getDouble(base, fieldOffset); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putDouble(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putDouble(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putDouble(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putDouble(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putDouble(base, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putDouble(base, fieldOffset, ((Float) value).floatValue()); + return; + } + if (value instanceof Double) { + unsafe.putDouble(base, fieldOffset, ((Double) value).doubleValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(d); + } + unsafe.putDouble(base, fieldOffset, d); + } + } + + public static class UnsafeStaticFloatFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticFloatFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Float(getFloat(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return unsafe.getFloat(base, fieldOffset); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getFloat(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putFloat(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putFloat(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putFloat(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putFloat(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putFloat(base, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putFloat(base, fieldOffset, ((Float) value).floatValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(f); + } + unsafe.putFloat(base, fieldOffset, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticIntegerFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticIntegerFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Integer(getInt(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return unsafe.getInt(base, fieldOffset); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putInt(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putInt(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putInt(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putInt(base, fieldOffset, ((Integer) value).intValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(i); + } + unsafe.putInt(base, fieldOffset, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticLongFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticLongFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Long(getLong(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return unsafe.getLong(base, fieldOffset); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putLong(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putLong(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putLong(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putLong(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putLong(base, fieldOffset, ((Long) value).longValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(l); + } + unsafe.putLong(base, fieldOffset, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticObjectFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticObjectFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return unsafe.getObject(base, fieldOffset); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value != null) { + if (!field.getType().isAssignableFrom(value.getClass())) { + throwSetIllegalArgumentException(value); + } + } + unsafe.putObject(base, fieldOffset, value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeStaticShortFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { + UnsafeStaticShortFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Short(getShort(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return unsafe.getShort(base, fieldOffset); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putShort(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putShort(base, fieldOffset, ((Short) value).shortValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setShort(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + if (isFinal) { + throwFinalFieldIllegalAccessException(s); + } + unsafe.putShort(base, fieldOffset, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedBooleanFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedBooleanFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Boolean(getBoolean(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getBooleanVolatile(obj, fieldOffset); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Boolean) { + unsafe.putBooleanVolatile(obj, fieldOffset, ((Boolean) value).booleanValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(z); + } + unsafe.putBooleanVolatile(obj, fieldOffset, z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedByteFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedByteFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Byte(getByte(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getByteVolatile(obj, fieldOffset); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putByteVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(b); + } + unsafe.putByteVolatile(obj, fieldOffset, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedCharacterFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedCharacterFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Character(getChar(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getCharVolatile(obj, fieldOffset); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Character) { + unsafe.putCharVolatile(obj, fieldOffset, ((Character) value).charValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(c); + } + unsafe.putCharVolatile(obj, fieldOffset, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedDoubleFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedDoubleFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Double(getDouble(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getDoubleVolatile(obj, fieldOffset); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Float) value).floatValue()); + return; + } + if (value instanceof Double) { + unsafe.putDoubleVolatile(obj, fieldOffset, ((Double) value).doubleValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(d); + } + unsafe.putDoubleVolatile(obj, fieldOffset, d); + } + } + + public static class UnsafeQualifiedFloatFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedFloatFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Float(getFloat(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getFloatVolatile(obj, fieldOffset); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getFloat(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putFloatVolatile(obj, fieldOffset, ((Float) value).floatValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(f); + } + unsafe.putFloatVolatile(obj, fieldOffset, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedIntegerFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedIntegerFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Integer(getInt(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getIntVolatile(obj, fieldOffset); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putIntVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putIntVolatile(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putIntVolatile(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putIntVolatile(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(i); + } + unsafe.putIntVolatile(obj, fieldOffset, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedLongFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedLongFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Long(getLong(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getLongVolatile(obj, fieldOffset); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putLongVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putLongVolatile(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putLongVolatile(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putLongVolatile(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putLongVolatile(obj, fieldOffset, ((Long) value).longValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(l); + } + unsafe.putLongVolatile(obj, fieldOffset, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedObjectFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedObjectFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getObjectVolatile(obj, fieldOffset); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value != null) { + if (!field.getType().isAssignableFrom(value.getClass())) { + throwSetIllegalArgumentException(value); + } + } + unsafe.putObjectVolatile(obj, fieldOffset, value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedShortFieldAccessorImpl + extends UnsafeQualifiedFieldAccessorImpl + { + UnsafeQualifiedShortFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Short(getShort(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getShortVolatile(obj, fieldOffset); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putShortVolatile(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putShortVolatile(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setShort(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isReadOnly) { + throwFinalFieldIllegalAccessException(s); + } + unsafe.putShortVolatile(obj, fieldOffset, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeBooleanFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeBooleanFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Boolean(getBoolean(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getBoolean(obj, fieldOffset); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Boolean) { + unsafe.putBoolean(obj, fieldOffset, ((Boolean) value).booleanValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(z); + } + unsafe.putBoolean(obj, fieldOffset, z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeByteFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeByteFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Byte(getByte(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getByte(obj, fieldOffset); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putByte(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(b); + } + unsafe.putByte(obj, fieldOffset, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeCharacterFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeCharacterFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Character(getChar(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getChar(obj, fieldOffset); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Character) { + unsafe.putChar(obj, fieldOffset, ((Character) value).charValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(c); + } + unsafe.putChar(obj, fieldOffset, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeDoubleFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeDoubleFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Double(getDouble(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getDouble(obj, fieldOffset); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putDouble(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putDouble(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putDouble(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putDouble(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putDouble(obj, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putDouble(obj, fieldOffset, ((Float) value).floatValue()); + return; + } + if (value instanceof Double) { + unsafe.putDouble(obj, fieldOffset, ((Double) value).doubleValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(d); + } + unsafe.putDouble(obj, fieldOffset, d); + } + } + + public static class UnsafeFloatFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeFloatFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Float(getFloat(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getFloat(obj, fieldOffset); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getFloat(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putFloat(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putFloat(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putFloat(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putFloat(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putFloat(obj, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putFloat(obj, fieldOffset, ((Float) value).floatValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(f); + } + unsafe.putFloat(obj, fieldOffset, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + + + public static class UnsafeIntegerFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeIntegerFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Integer(getInt(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getInt(obj, fieldOffset); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putInt(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putInt(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putInt(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putInt(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(i); + } + unsafe.putInt(obj, fieldOffset, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeLongFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeLongFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Long(getLong(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getLong(obj, fieldOffset); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putLong(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putLong(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putLong(obj, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putLong(obj, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putLong(obj, fieldOffset, ((Long) value).longValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(l); + } + unsafe.putLong(obj, fieldOffset, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeObjectFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeObjectFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getObject(obj, fieldOffset); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value != null) { + if (!field.getType().isAssignableFrom(value.getClass())) { + throwSetIllegalArgumentException(value); + } + } + unsafe.putObject(obj, fieldOffset, value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeShortFieldAccessorImpl extends UnsafeFieldAccessorImpl { + UnsafeShortFieldAccessorImpl(Field field) { + super(field); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Short(getShort(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + ensureObj(obj); + return unsafe.getShort(obj, fieldOffset); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putShort(obj, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putShort(obj, fieldOffset, ((Short) value).shortValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setShort(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + ensureObj(obj); + if (isFinal) { + throwFinalFieldIllegalAccessException(s); + } + unsafe.putShort(obj, fieldOffset, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + + public static class UnsafeQualifiedStaticBooleanFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticBooleanFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Boolean(getBoolean(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + return unsafe.getBooleanVolatile(base, fieldOffset); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Boolean) { + unsafe.putBooleanVolatile(base, fieldOffset, ((Boolean) value).booleanValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(z); + } + unsafe.putBooleanVolatile(base, fieldOffset, z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticByteFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticByteFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Byte(getByte(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + return unsafe.getByteVolatile(base, fieldOffset); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getByte(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putByteVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(b); + } + unsafe.putByteVolatile(base, fieldOffset, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticCharacterFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticCharacterFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Character(getChar(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + return unsafe.getCharVolatile(base, fieldOffset); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getChar(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Character) { + unsafe.putCharVolatile(base, fieldOffset, ((Character) value).charValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(c); + } + unsafe.putCharVolatile(base, fieldOffset, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticDoubleFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticDoubleFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Double(getDouble(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return unsafe.getDoubleVolatile(base, fieldOffset); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Float) value).floatValue()); + return; + } + if (value instanceof Double) { + unsafe.putDoubleVolatile(base, fieldOffset, ((Double) value).doubleValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(obj, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(d); + } + unsafe.putDoubleVolatile(base, fieldOffset, d); + } + } + + public static class UnsafeQualifiedStaticFloatFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticFloatFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Float(getFloat(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return unsafe.getFloatVolatile(base, fieldOffset); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getFloat(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putFloatVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putFloatVolatile(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putFloatVolatile(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putFloatVolatile(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putFloatVolatile(base, fieldOffset, ((Long) value).longValue()); + return; + } + if (value instanceof Float) { + unsafe.putFloatVolatile(base, fieldOffset, ((Float) value).floatValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(obj, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(f); + } + unsafe.putFloatVolatile(base, fieldOffset, f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticIntegerFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticIntegerFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Integer(getInt(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return unsafe.getIntVolatile(base, fieldOffset); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getInt(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putIntVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putIntVolatile(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putIntVolatile(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putIntVolatile(base, fieldOffset, ((Integer) value).intValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setInt(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(i); + } + unsafe.putIntVolatile(base, fieldOffset, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticLongFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticLongFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Long(getLong(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return unsafe.getLongVolatile(base, fieldOffset); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getLong(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putLongVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putLongVolatile(base, fieldOffset, ((Short) value).shortValue()); + return; + } + if (value instanceof Character) { + unsafe.putLongVolatile(base, fieldOffset, ((Character) value).charValue()); + return; + } + if (value instanceof Integer) { + unsafe.putLongVolatile(base, fieldOffset, ((Integer) value).intValue()); + return; + } + if (value instanceof Long) { + unsafe.putLongVolatile(base, fieldOffset, ((Long) value).longValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setLong(obj, i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(l); + } + unsafe.putLongVolatile(base, fieldOffset, l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticObjectFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticObjectFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return unsafe.getObjectVolatile(base, fieldOffset); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + throw newGetShortIllegalArgumentException(); + } + + public int getInt(Object obj) throws IllegalArgumentException { + throw newGetIntIllegalArgumentException(); + } + + public long getLong(Object obj) throws IllegalArgumentException { + throw newGetLongIllegalArgumentException(); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + throw newGetFloatIllegalArgumentException(); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + throw newGetDoubleIllegalArgumentException(); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value != null) { + if (!field.getType().isAssignableFrom(value.getClass())) { + throwSetIllegalArgumentException(value); + } + } + unsafe.putObjectVolatile(base, fieldOffset, value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + public static class UnsafeQualifiedStaticShortFieldAccessorImpl + extends UnsafeQualifiedStaticFieldAccessorImpl + { + UnsafeQualifiedStaticShortFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field, isReadOnly); + } + + public Object get(Object obj) throws IllegalArgumentException { + return new Short(getShort(obj)); + } + + public boolean getBoolean(Object obj) throws IllegalArgumentException { + throw newGetBooleanIllegalArgumentException(); + } + + public byte getByte(Object obj) throws IllegalArgumentException { + throw newGetByteIllegalArgumentException(); + } + + public char getChar(Object obj) throws IllegalArgumentException { + throw newGetCharIllegalArgumentException(); + } + + public short getShort(Object obj) throws IllegalArgumentException { + return unsafe.getShortVolatile(base, fieldOffset); + } + + public int getInt(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public long getLong(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public float getFloat(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public double getDouble(Object obj) throws IllegalArgumentException { + return getShort(obj); + } + + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(value); + } + if (value == null) { + throwSetIllegalArgumentException(value); + } + if (value instanceof Byte) { + unsafe.putShortVolatile(base, fieldOffset, ((Byte) value).byteValue()); + return; + } + if (value instanceof Short) { + unsafe.putShortVolatile(base, fieldOffset, ((Short) value).shortValue()); + return; + } + throwSetIllegalArgumentException(value); + } + + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(z); + } + + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setShort(obj, b); + } + + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(c); + } + + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + if (isReadOnly) { + throwFinalFieldIllegalAccessException(s); + } + unsafe.putShortVolatile(base, fieldOffset, s); + } + + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(i); + } + + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(l); + } + + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(f); + } + + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + throwSetIllegalArgumentException(d); + } + } + + +} diff --git a/src/Java/sun/repackage/UnsafeFieldAccessorImpl.java b/src/Java/sun/repackage/UnsafeFieldAccessorImpl.java new file mode 100644 index 0000000000..fbcc99bae9 --- /dev/null +++ b/src/Java/sun/repackage/UnsafeFieldAccessorImpl.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2001, 2011, 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.repackage; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** Base class for sun.misc.Unsafe-based FieldAccessors. The + observation is that there are only nine types of fields from the + standpoint of reflection code: the eight primitive types and + Object. Using class Unsafe instead of generated bytecodes saves + memory and loading time for the dynamically-generated + FieldAccessors. */ + +abstract class UnsafeFieldAccessorImpl extends FieldAccessorImpl { + static final Unsafe unsafe = Unsafe.getUnsafe(); + + protected final Field field; + protected final long fieldOffset; + protected final boolean isFinal; + + UnsafeFieldAccessorImpl(Field field) { + this.field = field; + if (Modifier.isStatic(field.getModifiers())) + fieldOffset = unsafe.staticFieldOffset(field); + else + fieldOffset = unsafe.objectFieldOffset(field); + isFinal = Modifier.isFinal(field.getModifiers()); + } + + protected void ensureObj(Object o) { + // NOTE: will throw NullPointerException, as specified, if o is null + if (!field.getDeclaringClass().isAssignableFrom(o.getClass())) { + throwSetIllegalArgumentException(o); + } + } + + private String getQualifiedFieldName() { + return field.getDeclaringClass().getName() + "." +field.getName(); + } + + protected IllegalArgumentException newGetIllegalArgumentException(String type) { + return new IllegalArgumentException( + "Attempt to get "+field.getType().getName()+" field \"" + + getQualifiedFieldName() + "\" with illegal data type conversion to "+type + ); + } + + protected void throwFinalFieldIllegalAccessException(String attemptedType, + String attemptedValue) + throws IllegalAccessException { + throw new IllegalAccessException(getSetMessage(attemptedType, attemptedValue)); + + } + protected void throwFinalFieldIllegalAccessException(Object o) throws IllegalAccessException { + throwFinalFieldIllegalAccessException(o != null ? o.getClass().getName() : "", ""); + } + + protected void throwFinalFieldIllegalAccessException(boolean z) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("boolean", Boolean.toString(z)); + } + + protected void throwFinalFieldIllegalAccessException(char b) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("char", Character.toString(b)); + } + + protected void throwFinalFieldIllegalAccessException(byte b) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("byte", Byte.toString(b)); + } + + protected void throwFinalFieldIllegalAccessException(short b) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("short", Short.toString(b)); + } + + protected void throwFinalFieldIllegalAccessException(int i) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("int", Integer.toString(i)); + } + + protected void throwFinalFieldIllegalAccessException(long i) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("long", Long.toString(i)); + } + + protected void throwFinalFieldIllegalAccessException(float f) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("float", Float.toString(f)); + } + + protected void throwFinalFieldIllegalAccessException(double f) throws IllegalAccessException { + throwFinalFieldIllegalAccessException("double", Double.toString(f)); + } + + protected IllegalArgumentException newGetBooleanIllegalArgumentException() { + return newGetIllegalArgumentException("boolean"); + } + + protected IllegalArgumentException newGetByteIllegalArgumentException() { + return newGetIllegalArgumentException("byte"); + } + + protected IllegalArgumentException newGetCharIllegalArgumentException() { + return newGetIllegalArgumentException("char"); + } + + protected IllegalArgumentException newGetShortIllegalArgumentException() { + return newGetIllegalArgumentException("short"); + } + + protected IllegalArgumentException newGetIntIllegalArgumentException() { + return newGetIllegalArgumentException("int"); + } + + protected IllegalArgumentException newGetLongIllegalArgumentException() { + return newGetIllegalArgumentException("long"); + } + + protected IllegalArgumentException newGetFloatIllegalArgumentException() { + return newGetIllegalArgumentException("float"); + } + + protected IllegalArgumentException newGetDoubleIllegalArgumentException() { + return newGetIllegalArgumentException("double"); + } + + protected String getSetMessage(String attemptedType, String attemptedValue) { + String err = "Can not set"; + if (Modifier.isStatic(field.getModifiers())) + err += " static"; + if (isFinal) + err += " final"; + err += " " + field.getType().getName() + " field " + getQualifiedFieldName() + " to "; + if (attemptedValue.length() > 0) { + err += "(" + attemptedType + ")" + attemptedValue; + } else { + if (attemptedType.length() > 0) + err += attemptedType; + else + err += "null value"; + } + return err; + } + + protected void throwSetIllegalArgumentException(String attemptedType, + String attemptedValue) { + throw new IllegalArgumentException(getSetMessage(attemptedType,attemptedValue)); + } + + protected void throwSetIllegalArgumentException(Object o) { + throwSetIllegalArgumentException(o != null ? o.getClass().getName() : "", ""); + } + + protected void throwSetIllegalArgumentException(boolean b) { + throwSetIllegalArgumentException("boolean", Boolean.toString(b)); + } + + protected void throwSetIllegalArgumentException(byte b) { + throwSetIllegalArgumentException("byte", Byte.toString(b)); + } + + protected void throwSetIllegalArgumentException(char c) { + throwSetIllegalArgumentException("char", Character.toString(c)); + } + + protected void throwSetIllegalArgumentException(short s) { + throwSetIllegalArgumentException("short", Short.toString(s)); + } + + protected void throwSetIllegalArgumentException(int i) { + throwSetIllegalArgumentException("int", Integer.toString(i)); + } + + protected void throwSetIllegalArgumentException(long l) { + throwSetIllegalArgumentException("long", Long.toString(l)); + } + + protected void throwSetIllegalArgumentException(float f) { + throwSetIllegalArgumentException("float", Float.toString(f)); + } + + protected void throwSetIllegalArgumentException(double d) { + throwSetIllegalArgumentException("double", Double.toString(d)); + } + +} diff --git a/src/Java/sun/repackage/UnsafeQualifiedFieldAccessorImpl.java b/src/Java/sun/repackage/UnsafeQualifiedFieldAccessorImpl.java new file mode 100644 index 0000000000..d60c3696dd --- /dev/null +++ b/src/Java/sun/repackage/UnsafeQualifiedFieldAccessorImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004, 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.repackage; + +import java.lang.reflect.Field; + +/** + * Base class for sun.misc.Unsafe-based FieldAccessors for fields with + * final or volatile qualifiers. These differ from unqualified + * versions in that (1) they check for read-only status (2) they use + * the volatile forms of Unsafe get/put methods. (When accessed via + * reflection, finals act as slightly "lighter" forms of volatiles. So + * the volatile forms are heavier than necessary in terms of + * underlying reordering rules and memory barriers, but preserve + * correctness.) + */ + +abstract class UnsafeQualifiedFieldAccessorImpl + extends UnsafeFieldAccessorImpl +{ + protected final boolean isReadOnly; + + UnsafeQualifiedFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field); + this.isReadOnly = isReadOnly; + } +} diff --git a/src/Java/sun/repackage/UnsafeQualifiedStaticFieldAccessorImpl.java b/src/Java/sun/repackage/UnsafeQualifiedStaticFieldAccessorImpl.java new file mode 100644 index 0000000000..c68b6c9cbd --- /dev/null +++ b/src/Java/sun/repackage/UnsafeQualifiedStaticFieldAccessorImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2004, 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.repackage; + +import java.lang.reflect.Field; + +/** Base class for sun.misc.Unsafe-based FieldAccessors for final or + volatile static fields. */ + +abstract class UnsafeQualifiedStaticFieldAccessorImpl + extends UnsafeStaticFieldAccessorImpl +{ + protected final boolean isReadOnly; + + UnsafeQualifiedStaticFieldAccessorImpl(Field field, boolean isReadOnly) { + super(field); + this.isReadOnly = isReadOnly; + } +} diff --git a/src/Java/sun/repackage/UnsafeStaticFieldAccessorImpl.java b/src/Java/sun/repackage/UnsafeStaticFieldAccessorImpl.java new file mode 100644 index 0000000000..06a91d752c --- /dev/null +++ b/src/Java/sun/repackage/UnsafeStaticFieldAccessorImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2001, 2012, 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.repackage; + +import java.lang.reflect.Field; + +/** Base class for sun.misc.Unsafe-based FieldAccessors for static + fields. The observation is that there are only nine types of + fields from the standpoint of reflection code: the eight primitive + types and Object. Using class Unsafe instead of generated + bytecodes saves memory and loading time for the + dynamically-generated FieldAccessors. */ + +abstract class UnsafeStaticFieldAccessorImpl extends UnsafeFieldAccessorImpl { + static { + Reflection.registerFieldsToFilter(UnsafeStaticFieldAccessorImpl.class, + new String[] { "base" }); + } + + protected final Object base; // base + + UnsafeStaticFieldAccessorImpl(Field field) { + super(field); + base = unsafe.staticFieldBase(field); + } +} |