/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* ProxyGenerator contains the code to generate a dynamic proxy class
* for the java.lang.reflect.Proxy API.
*
* The external interfaces to ProxyGenerator is the static
* "generateProxyClass" method.
*
* @author Peter Jones
* @since 1.3
*/
public class ProxyGenerator {
/*
* In the comments below, "JVMS" refers to The Java Virtual Machine
* Specification Second Edition and "JLS" refers to the original
* version of The Java Language Specification, unless otherwise
* specified.
*/
/* generate 1.5-era class file version */
/*
* beginning of constants copied from
* sun.tools.java.RuntimeConstants (which no longer exists):
*/
/* constant pool tags */
/* access and modifier flags */
// private static final int ACC_PROTECTED = 0x00000004;
// private static final int ACC_SYNCHRONIZED = 0x00000020;
// private static final int ACC_VOLATILE = 0x00000040;
// private static final int ACC_TRANSIENT = 0x00000080;
// private static final int ACC_NATIVE = 0x00000100;
// private static final int ACC_INTERFACE = 0x00000200;
// private static final int ACC_ABSTRACT = 0x00000400;
// private static final int ACC_STRICT = 0x00000800;
/* opcodes */
// private static final int opc_nop = 0;
// private static final int opc_iconst_m1 = 2;
// private static final int opc_iconst_1 = 4;
// private static final int opc_iconst_2 = 5;
// private static final int opc_iconst_3 = 6;
// private static final int opc_iconst_4 = 7;
// private static final int opc_iconst_5 = 8;
// private static final int opc_lconst_0 = 9;
// private static final int opc_lconst_1 = 10;
// private static final int opc_fconst_0 = 11;
// private static final int opc_fconst_1 = 12;
// private static final int opc_fconst_2 = 13;
// private static final int opc_dconst_0 = 14;
// private static final int opc_dconst_1 = 15;
// private static final int opc_ldc2_w = 20;
// private static final int opc_iload_1 = 27;
// private static final int opc_iload_2 = 28;
// private static final int opc_iload_3 = 29;
// private static final int opc_lload_1 = 31;
// private static final int opc_lload_2 = 32;
// private static final int opc_lload_3 = 33;
// private static final int opc_fload_1 = 35;
// private static final int opc_fload_2 = 36;
// private static final int opc_fload_3 = 37;
// private static final int opc_dload_1 = 39;
// private static final int opc_dload_2 = 40;
// private static final int opc_dload_3 = 41;
// private static final int opc_aload_1 = 43;
// private static final int opc_aload_2 = 44;
// private static final int opc_aload_3 = 45;
// private static final int opc_iaload = 46;
// private static final int opc_laload = 47;
// private static final int opc_faload = 48;
// private static final int opc_daload = 49;
// private static final int opc_aaload = 50;
// private static final int opc_baload = 51;
// private static final int opc_caload = 52;
// private static final int opc_saload = 53;
// private static final int opc_istore = 54;
// private static final int opc_lstore = 55;
// private static final int opc_fstore = 56;
// private static final int opc_dstore = 57;
// private static final int opc_istore_0 = 59;
// private static final int opc_istore_1 = 60;
// private static final int opc_istore_2 = 61;
// private static final int opc_istore_3 = 62;
// private static final int opc_lstore_0 = 63;
// private static final int opc_lstore_1 = 64;
// private static final int opc_lstore_2 = 65;
// private static final int opc_lstore_3 = 66;
// private static final int opc_fstore_0 = 67;
// private static final int opc_fstore_1 = 68;
// private static final int opc_fstore_2 = 69;
// private static final int opc_fstore_3 = 70;
// private static final int opc_dstore_0 = 71;
// private static final int opc_dstore_1 = 72;
// private static final int opc_dstore_2 = 73;
// private static final int opc_dstore_3 = 74;
// private static final int opc_astore_1 = 76;
// private static final int opc_astore_2 = 77;
// private static final int opc_astore_3 = 78;
// private static final int opc_iastore = 79;
// private static final int opc_lastore = 80;
// private static final int opc_fastore = 81;
// private static final int opc_dastore = 82;
// private static final int opc_bastore = 84;
// private static final int opc_castore = 85;
// private static final int opc_sastore = 86;
// private static final int opc_pop2 = 88;
// private static final int opc_dup_x1 = 90;
// private static final int opc_dup_x2 = 91;
// private static final int opc_dup2 = 92;
// private static final int opc_dup2_x1 = 93;
// private static final int opc_dup2_x2 = 94;
// private static final int opc_swap = 95;
// private static final int opc_iadd = 96;
// private static final int opc_ladd = 97;
// private static final int opc_fadd = 98;
// private static final int opc_dadd = 99;
// private static final int opc_isub = 100;
// private static final int opc_lsub = 101;
// private static final int opc_fsub = 102;
// private static final int opc_dsub = 103;
// private static final int opc_imul = 104;
// private static final int opc_lmul = 105;
// private static final int opc_fmul = 106;
// private static final int opc_dmul = 107;
// private static final int opc_idiv = 108;
// private static final int opc_ldiv = 109;
// private static final int opc_fdiv = 110;
// private static final int opc_ddiv = 111;
// private static final int opc_irem = 112;
// private static final int opc_lrem = 113;
// private static final int opc_frem = 114;
// private static final int opc_drem = 115;
// private static final int opc_ineg = 116;
// private static final int opc_lneg = 117;
// private static final int opc_fneg = 118;
// private static final int opc_dneg = 119;
// private static final int opc_ishl = 120;
// private static final int opc_lshl = 121;
// private static final int opc_ishr = 122;
// private static final int opc_lshr = 123;
// private static final int opc_iushr = 124;
// private static final int opc_lushr = 125;
// private static final int opc_iand = 126;
// private static final int opc_land = 127;
// private static final int opc_ior = 128;
// private static final int opc_lor = 129;
// private static final int opc_ixor = 130;
// private static final int opc_lxor = 131;
// private static final int opc_iinc = 132;
// private static final int opc_i2l = 133;
// private static final int opc_i2f = 134;
// private static final int opc_i2d = 135;
// private static final int opc_l2i = 136;
// private static final int opc_l2f = 137;
// private static final int opc_l2d = 138;
// private static final int opc_f2i = 139;
// private static final int opc_f2l = 140;
// private static final int opc_f2d = 141;
// private static final int opc_d2i = 142;
// private static final int opc_d2l = 143;
// private static final int opc_d2f = 144;
// private static final int opc_i2b = 145;
// private static final int opc_i2c = 146;
// private static final int opc_i2s = 147;
// private static final int opc_lcmp = 148;
// private static final int opc_fcmpl = 149;
// private static final int opc_fcmpg = 150;
// private static final int opc_dcmpl = 151;
// private static final int opc_dcmpg = 152;
// private static final int opc_ifeq = 153;
// private static final int opc_ifne = 154;
// private static final int opc_iflt = 155;
// private static final int opc_ifge = 156;
// private static final int opc_ifgt = 157;
// private static final int opc_ifle = 158;
// private static final int opc_if_icmpeq = 159;
// private static final int opc_if_icmpne = 160;
// private static final int opc_if_icmplt = 161;
// private static final int opc_if_icmpge = 162;
// private static final int opc_if_icmpgt = 163;
// private static final int opc_if_icmple = 164;
// private static final int opc_if_acmpeq = 165;
// private static final int opc_if_acmpne = 166;
// private static final int opc_goto = 167;
// private static final int opc_jsr = 168;
// private static final int opc_ret = 169;
// private static final int opc_tableswitch = 170;
// private static final int opc_lookupswitch = 171;
// private static final int opc_putfield = 181;
// private static final int opc_newarray = 188;
// private static final int opc_arraylength = 190;
// private static final int opc_instanceof = 193;
// private static final int opc_monitorenter = 194;
// private static final int opc_monitorexit = 195;
// private static final int opc_multianewarray = 197;
// private static final int opc_ifnull = 198;
// private static final int opc_ifnonnull = 199;
// private static final int opc_goto_w = 200;
// private static final int opc_jsr_w = 201;
// end of constants copied from sun.tools.java.RuntimeConstants
/** name of the superclass of proxy classes */
/** name of field for storing a proxy instance's invocation handler */
/** debugging flag for saving generated class files */
private final static boolean saveGeneratedFiles =
new GetBooleanAction(
"sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
/**
* Generate a proxy class given a name and a list of proxy interfaces.
*/
Class[] interfaces)
{
if (saveGeneratedFiles) {
try {
return null;
} catch (IOException e) {
throw new InternalError(
"I/O exception saving generated file: " + e);
}
}
});
}
return classFile;
}
/* preloaded Method objects for methods in java.lang.Object */
static {
try {
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
/** name of proxy class */
/** proxy interfaces */
/** constant pool of class being generated */
/** FieldInfo struct for each field of generated class */
/** MethodInfo struct for each method of generated class */
/**
* maps method signature string to list of ProxyMethod objects for
* proxy methods with that signature
*/
/** count of ProxyMethod objects added to proxyMethods */
/**
* Construct a ProxyGenerator to generate a proxy class with the
* specified name and for the given interfaces.
*
* A ProxyGenerator object contains the state for the ongoing
* generation of a particular proxy class.
*/
this.interfaces = interfaces;
}
/**
* Generate a class file for the proxy class. This method drives the
* class file generation process.
*/
private byte[] generateClassFile() {
/* ============================================================
* Step 1: Assemble ProxyMethod objects for all methods to
* generate proxy dispatching code for.
*/
/*
* Record that proxy methods are needed for the hashCode, equals,
* and toString methods of java.lang.Object. This is done before
* the methods from the proxy interfaces so that the methods from
* java.lang.Object take precedence over duplicate methods in the
* proxy interfaces.
*/
/*
* Now record all of the methods from the proxy interfaces, giving
* earlier interfaces precedence over later ones with duplicate
* methods.
*/
}
}
/*
* For each set of proxy methods with the same signature,
* verify that the methods' return types are compatible.
*/
}
/* ============================================================
* Step 2: Assemble FieldInfo and MethodInfo structs for all of
* fields and methods in the class we are generating.
*/
try {
// add static field for method's Method object
ACC_PRIVATE | ACC_STATIC));
// generate code for proxy method and add it
}
}
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
throw new IllegalArgumentException("method limit exceeded");
}
throw new IllegalArgumentException("field limit exceeded");
}
/* ============================================================
* Step 3: Write the final class file.
*/
/*
* Make sure that constant pool indexes are reserved for the
* following items before starting to write the final class file.
*/
}
/*
* Disallow new constant pool additions beyond this point, since
* we are about to write the final constant pool table.
*/
cp.setReadOnly();
try {
/*
* Write all the items of the "ClassFile" structure.
* See JVMS section 4.1.
*/
// u4 magic;
// u2 minor_version;
// u2 major_version;
// u2 access_flags;
// u2 this_class;
// u2 super_class;
// u2 interfaces_count;
// u2 interfaces[interfaces_count];
}
// u2 fields_count;
// field_info fields[fields_count];
}
// u2 methods_count;
// method_info methods[methods_count];
for (MethodInfo m : methods) {
}
// u2 attributes_count;
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
return bout.toByteArray();
}
/**
* Add another method to be proxied, either by creating a new
* ProxyMethod object or augmenting an old one for a duplicate
* method.
*
* "fromClass" indicates the proxy interface that the method was
* found through, which may be different from (a subinterface of)
* the method's "declaring class". Note that the first Method
* object passed for a given name and descriptor identifies the
* Method object (and thus the declaring class) that will be
* passed to the invocation handler's "invoke" method for a given
* set of duplicate methods.
*/
if (sigmethods != null) {
/*
* Found a match: reduce exception types to the
* greatest set of exceptions that can thrown
* compatibly with the throws clauses of both
* overridden methods.
*/
return;
}
}
} else {
}
}
/**
* For a given set of proxy methods with the same signature, check
* that their return types are compatible according to the Proxy
* specification.
*
* Specifically, if there is more than one such method, then all
* of the return types must be reference types, and there must be
* one return type that is assignable to each of the rest of them.
*/
/*
* If there is only one method with a given signature, there
* cannot be a conflict. This is the only case in which a
* primitive (or void) return type is allowed.
*/
return;
}
/*
* List of return types that are not yet known to be
* assignable from ("covered" by) any of the others.
*/
if (newReturnType.isPrimitive()) {
throw new IllegalArgumentException(
"methods with same signature " +
pm.parameterTypes) +
" but incompatible return types: " +
}
boolean added = false;
/*
* Compare the new return type to the existing uncovered
* return types.
*/
/*
* If an existing uncovered return type is assignable
* to this new one, then we can forget the new one.
*/
assert !added;
continue nextNewReturnType;
}
/*
* If the new return type is assignable to an existing
* uncovered one, then should replace the existing one
* with the new one (or just forget the existing one,
* if the new one has already be put in the list).
*/
// (we can assume that each return type is unique)
if (!added) {
added = true;
} else {
}
}
}
/*
* If we got through the list of existing uncovered return
* types without an assignability relationship, then add
* the new return type to the list of uncovered ones.
*/
if (!added) {
}
}
/*
* We shouldn't end up with more than one return type that is
* not assignable from any of the others.
*/
throw new IllegalArgumentException(
"methods with same signature " +
" but incompatible return types: " + uncoveredReturnTypes);
}
}
/**
* A FieldInfo object contains information about a particular field
* in the class being generated. The class mirrors the data items of
* the "field_info" structure of the class file format (see JVMS 4.5).
*/
private class FieldInfo {
public int accessFlags;
this.descriptor = descriptor;
this.accessFlags = accessFlags;
/*
* Make sure that constant pool indexes are reserved for the
* following items before starting to write the final class file.
*/
}
/*
* Write all the items of the "field_info" structure.
* See JVMS section 4.5.
*/
// u2 access_flags;
// u2 name_index;
// u2 descriptor_index;
// u2 attributes_count;
}
}
/**
* An ExceptionTableEntry object holds values for the data items of
* an entry in the "exception_table" item of the "Code" attribute of
* "method_info" structures (see JVMS 4.7.3).
*/
private static class ExceptionTableEntry {
public short startPc;
public short endPc;
public short handlerPc;
public short catchType;
{
}
};
/**
* A MethodInfo object contains information about a particular method
* in the class being generated. This class mirrors the data items of
* the "method_info" structure of the class file format (see JVMS 4.6).
*/
private class MethodInfo {
public int accessFlags;
public short maxStack;
public short maxLocals;
new ArrayList<ExceptionTableEntry>();
public short[] declaredExceptions;
this.descriptor = descriptor;
this.accessFlags = accessFlags;
/*
* Make sure that constant pool indexes are reserved for the
* following items before starting to write the final class file.
*/
}
/*
* Write all the items of the "method_info" structure.
* See JVMS section 4.6.
*/
// u2 access_flags;
// u2 name_index;
// u2 descriptor_index;
// u2 attributes_count;
// Write "Code" attribute. See JVMS section 4.7.3.
// u2 attribute_name_index;
// u4 attribute_length;
// u2 max_stack;
// u2 max_locals;
// u2 code_length;
// u1 code[code_length];
// u2 exception_table_length;
for (ExceptionTableEntry e : exceptionTable) {
// u2 start_pc;
// u2 end_pc;
// u2 handler_pc;
// u2 catch_type;
}
// u2 attributes_count;
// write "Exceptions" attribute. See JVMS section 4.7.4.
// u2 attribute_name_index;
// u4 attributes_length;
// u2 number_of_exceptions;
// u2 exception_index_table[number_of_exceptions];
}
}
}
/**
* A ProxyMethod object represents a proxy method in the proxy class
* being generated: a method whose implementation will encode and
* dispatch invocations to the proxy instance's invocation handler.
*/
private class ProxyMethod {
{
this.methodName = methodName;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.exceptionTypes = exceptionTypes;
}
/**
* Return a MethodInfo object for this method, including generating
* the code and exception table entry.
*/
ACC_PUBLIC | ACC_FINAL);
int nextSlot = 1;
parameterSlot[i] = nextSlot;
}
int localSlot0 = nextSlot;
methodFieldName, "Ljava/lang/reflect/Method;"));
code_ipush(i, out);
}
} else {
}
"invoke",
if (returnType == void.class) {
} else {
}
}
}
throw new IllegalArgumentException("code size limit exceeded");
}
}
return minfo;
}
/**
* Generate code for wrapping an argument of the given type
* whose value can be found at the specified local variable
* index, in order for it to be passed (as an Object) to the
* invocation handler's "invoke" method. The code is written
* to the supplied stream.
*/
throws IOException
{
if (type.isPrimitive()) {
if (type == int.class ||
type == boolean.class ||
type == byte.class ||
type == char.class ||
type == short.class)
{
} else if (type == long.class) {
} else if (type == float.class) {
} else if (type == double.class) {
} else {
throw new AssertionError();
}
} else {
}
}
/**
* Generate code for unwrapping a return value of the given
* type from the invocation handler's "invoke" method (as type
* Object) to its correct type. The code is written to the
* supplied stream.
*/
throws IOException
{
if (type.isPrimitive()) {
if (type == int.class ||
type == boolean.class ||
type == byte.class ||
type == char.class ||
type == short.class)
{
} else if (type == long.class) {
} else if (type == float.class) {
} else if (type == double.class) {
} else {
throw new AssertionError();
}
} else {
}
}
/**
* Generate code for initializing the static field that stores
* the Method object for this proxy method. The code is written
* to the supplied stream.
*/
throws IOException
{
code_ipush(i, out);
if (parameterTypes[i].isPrimitive()) {
} else {
}
}
"getMethod",
methodFieldName, "Ljava/lang/reflect/Method;"));
}
}
/**
* Generate the constructor method for the proxy class.
*/
"<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
"<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
return minfo;
}
/**
* Generate the static initializer method for the proxy class.
*/
int localSlot0 = 1;
}
}
throw new IllegalArgumentException("code size limit exceeded");
}
return minfo;
}
/*
* =============== Code Generation Utility Methods ===============
*/
/*
* The following methods generate code for the load or store operation
* indicated by their name for the given local variable. The code is
* written to the supplied stream.
*/
throws IOException
{
}
throws IOException
{
}
throws IOException
{
}
throws IOException
{
}
throws IOException
{
}
// private void code_istore(int lvar, DataOutputStream out)
// throws IOException
// {
// codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
// }
// private void code_lstore(int lvar, DataOutputStream out)
// throws IOException
// {
// codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
// }
// private void code_fstore(int lvar, DataOutputStream out)
// throws IOException
// {
// codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
// }
// private void code_dstore(int lvar, DataOutputStream out)
// throws IOException
// {
// codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
// }
throws IOException
{
}
/**
* Generate code for a load or store instruction for the given local
* variable. The code is written to the supplied stream.
*
* "opcode" indicates the opcode form of the desired load or store
* instruction that takes an explicit local variable index, and
* "opcode_0" indicates the corresponding form of the instruction
* with the implicit index 0.
*/
throws IOException
{
if (lvar <= 3) {
} else if (lvar <= 0xFF) {
} else {
/*
* Use the "wide" instruction modifier for local variable
* indexes that do not fit into an unsigned byte.
*/
}
}
/**
* Generate code for an "ldc" instruction for the given constant pool
* index (the "ldc_w" instruction is used if the index does not fit
* into an unsigned byte). The code is written to the supplied stream.
*/
throws IOException
{
if (index <= 0xFF) {
} else {
}
}
/**
* Generate code to push a constant integer value on to the operand
* stack, using the "iconst_<i>", "bipush", or "sipush" instructions
* depending on the size of the value. The code is written to the
* supplied stream.
*/
throws IOException
{
} else {
throw new AssertionError();
}
}
/**
* Generate code to invoke the Class.forName with the name of the given
* class to get its Class object at runtime. The code is written to
* the supplied stream. Note that the code generated by this method
* may caused the checked ClassNotFoundException to be thrown.
*/
throws IOException
{
}
/*
* ==================== General Utility Methods ====================
*/
/**
* Convert a fully qualified class name that uses '.' as the package
* separator, the external representation used by the Java language
* and APIs, to a fully qualified class name that uses '/' as the
* package separator, the representation used in the class file
* format (see JVMS section 4.2).
*/
}
/**
* Return the "method descriptor" string for a method with the given
* parameter types and return type. See JVMS section 4.3.3.
*/
{
return getParameterDescriptors(parameterTypes) +
}
/**
* Return the list of "parameter descriptor" strings enclosed in
* parentheses corresponding to the given parameter types (in other
* words, a method descriptor without a return descriptor). This
* string is useful for constructing string keys for methods without
* regard to their return type.
*/
}
}
/**
* Return the "field type" string for the given type, appropriate for
* a field descriptor, a parameter descriptor, or a return descriptor
* other than "void". See JVMS section 4.3.2.
*/
if (type.isPrimitive()) {
/*
* According to JLS 20.3.2, the getName() method on Class does
* return the VM type descriptor format for array classes (only);
* using that should be quicker than the otherwise obvious code:
*
* return "[" + getTypeDescriptor(type.getComponentType());
*/
} else {
}
}
/**
* Returns a human-readable string representing the signature of a
* method with the given name and parameter types.
*/
{
if (i > 0) {
}
int dimensions = 0;
while (parameterType.isArray()) {
dimensions++;
}
while (dimensions-- > 0) {
}
}
}
/**
* Return the number of abstract "words", or consecutive local variable
* indexes, required to contain a value of the given type. See JVMS
* section 3.6.1.
*
* Note that the original version of the JVMS contained a definition of
* this abstract notion of a "word" in section 3.4, but that definition
* was removed for the second edition.
*/
return 2;
} else {
return 1;
}
}
/**
* Add to the given list all of the types in the "from" array that
* are not already contained in the list and are assignable to at
* least one of the types in the "with" array.
*
* This method is useful for computing the greatest common set of
* declared exceptions from duplicate methods inherited from
* different interfaces.
*/
{
break;
}
}
}
}
}
/**
* Given the exceptions declared in the throws clause of a proxy method,
* compute the exceptions that need to be caught from the invocation
* handler's invoke method and rethrown intact in the method's
* implementation before catching other Throwables and wrapping them
* in UndeclaredThrowableExceptions.
*
* The exceptions to be caught are returned in a List object. Each
* exception in the returned list is guaranteed to not be a subclass of
* any of the other exceptions in the list, so the catch blocks for
* these exceptions may be generated in any order relative to each other.
*
* Error and RuntimeException are each always contained by the returned
* list (if none of their superclasses are contained), since those
* unchecked exceptions should always be rethrown intact, and thus their
* subclasses will never appear in the returned list.
*
* The returned List will be empty if java.lang.Throwable is in the
* given list of declared exceptions, indicating that no exceptions
* need to be caught.
*/
// unique exceptions to catch
/*
* If Throwable is declared to be thrown by the proxy method,
* then no catch blocks are necessary, because the invoke
* can, at most, throw Throwable anyway.
*/
uniqueList.clear();
break;
/*
* Ignore types that cannot be thrown by the invoke method.
*/
continue;
}
/*
* Compare this exception against the current list of
* exceptions that need to be caught:
*/
/*
* if a superclass of this exception is already on
* the list to catch, then ignore this one and continue;
*/
continue nextException;
/*
* if a subclass of this exception is on the list
* to catch, then remove it;
*/
uniqueList.remove(j);
} else {
j++; // else continue comparing.
}
}
// This exception is unique (so far): add it to the list to catch.
}
return uniqueList;
}
/**
* A PrimitiveTypeInfo object contains assorted information about
* a primitive type in its public fields. The struct for a particular
* primitive type can be obtained using the static "get" method.
*/
private static class PrimitiveTypeInfo {
/** "base type" used in various descriptors (see JVMS section 4.3.2) */
/** name of corresponding wrapper class */
/** method descriptor for wrapper class "valueOf" factory method */
/** name of wrapper class method for retrieving primitive value */
/** descriptor of same method */
static {
}
}
assert primitiveClass.isPrimitive();
}
}
}
/**
* A ConstantPool object represents the constant pool of a class file
* being generated. This representation of a constant pool is designed
* specifically for use by ProxyGenerator; in particular, it assumes
* that constant pool entries will not need to be resorted (for example,
* by their type, as the Java compiler does), so that the final index
* value can be assigned and used when an entry is first created.
*
* Note that new entries cannot be created after the constant pool has
* been written to a class file. To prevent such logic errors, a
* ConstantPool instance can be marked "read only", so that further
* attempts to add new entries will fail with a runtime exception.
*
* See JVMS section 4.4 for more information about the constant pool
* of a class file.
*/
private static class ConstantPool {
/**
* list of constant pool entries, in constant pool index order.
*
* This list is used when writing the constant pool to a stream
* and for assigning the next index value. Note that element 0
* of this list corresponds to constant pool index 1.
*/
/**
* maps constant pool data of all types to constant pool indexes.
*
* This map is used to look up the index of an existing entry for
* values of all types.
*/
/** true if no new constant pool entries may be added */
private boolean readOnly = false;
/**
* Get or assign the index for a CONSTANT_Utf8 entry.
*/
if (s == null) {
throw new NullPointerException();
}
return getValue(s);
}
/**
* Get or assign the index for a CONSTANT_Integer entry.
*/
public short getInteger(int i) {
}
/**
* Get or assign the index for a CONSTANT_Float entry.
*/
public short getFloat(float f) {
}
/**
* Get or assign the index for a CONSTANT_Class entry.
*/
return getIndirect(new IndirectEntry(
}
/**
* Get or assign the index for a CONSTANT_String entry.
*/
return getIndirect(new IndirectEntry(
}
/**
* Get or assign the index for a CONSTANT_FieldRef entry.
*/
{
return getIndirect(new IndirectEntry(
}
/**
* Get or assign the index for a CONSTANT_MethodRef entry.
*/
{
return getIndirect(new IndirectEntry(
}
/**
* Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
*/
{
return getIndirect(new IndirectEntry(
}
/**
* Get or assign the index for a CONSTANT_NameAndType entry.
*/
return getIndirect(new IndirectEntry(
}
/**
* Set this ConstantPool instance to be "read only".
*
* After this method has been called, further requests to get
* an index for a non-existent entry will cause an InternalError
* to be thrown instead of creating of the entry.
*/
public void setReadOnly() {
readOnly = true;
}
/**
* Write this constant pool to a stream as part of
* the class file format.
*
* This consists of writing the "constant_pool_count" and
* "constant_pool[]" items of the "ClassFile" structure, as
* described in JVMS section 4.1.
*/
// constant_pool_count: number of entries plus one
}
}
/**
* Add a new constant pool entry and return its index.
*/
/*
* Note that this way of determining the index of the
* added entry is wrong if this pool supports
* CONSTANT_Long or CONSTANT_Double entries.
*/
throw new IllegalArgumentException(
"constant pool size limit exceeded");
}
}
/**
* Get or assign the index for an entry of a type that contains
* a direct value. The type of the given object determines the
* type of the desired entry as follows:
*
* java.lang.String CONSTANT_Utf8
* java.lang.Integer CONSTANT_Integer
* java.lang.Float CONSTANT_Float
* java.lang.Long CONSTANT_Long
* java.lang.Double CONSTANT_DOUBLE
*/
return index.shortValue();
} else {
if (readOnly) {
throw new InternalError(
"late constant pool addition: " + key);
}
return i;
}
}
/**
* Get or assign the index for an entry of a type that contains
* references to other constant pool entries.
*/
return index.shortValue();
} else {
if (readOnly) {
throw new InternalError("late constant pool addition");
}
short i = addEntry(e);
return i;
}
}
/**
* Entry is the abstact superclass of all constant pool entry types
* that can be stored in the "pool" list; its purpose is to define a
* common method for writing constant pool entries to a class file.
*/
private static abstract class Entry {
throws IOException;
}
/**
* ValueEntry represents a constant pool entry of a type that
* contains a direct value (see the comments for the "getValue"
* method for a list of such types).
*
* ValueEntry objects are not used as keys for their entries in the
* Map "map", so no useful hashCode or equals methods are defined.
*/
}
} else {
}
}
}
/**
* IndirectEntry represents a constant pool entry of a type that
* references other constant pool entries, i.e., the following types:
*
* CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
* CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
* CONSTANT_NameAndType.
*
* Each of these entry types contains either one or two indexes of
* other constant pool entries.
*
* IndirectEntry objects are used as the keys for their entries in
* the Map "map", so the hashCode and equals methods are overridden
* to allow matching.
*/
private int tag;
private short index0;
private short index1;
/**
* Construct an IndirectEntry for a constant pool entry type
* that contains one index of another entry.
*/
this.index1 = 0;
}
/**
* Construct an IndirectEntry for a constant pool entry type
* that contains two indexes for other entries.
*/
}
/*
* If this entry type contains two indexes, write
* out the second, too.
*/
if (tag == CONSTANT_FIELD ||
tag == CONSTANT_METHOD ||
tag == CONSTANT_INTERFACEMETHOD ||
{
}
}
public int hashCode() {
}
if (obj instanceof IndirectEntry) {
{
return true;
}
}
return false;
}
}
}
}