You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2006/09/06 23:08:44 UTC
svn commit: r440871 [1/2] -
/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/
Author: ndbeyer
Date: Wed Sep 6 14:08:44 2006
New Revision: 440871
URL: http://svn.apache.org/viewvc?view=rev&rev=440871
Log:
Code cleanup; add braces, remove unecessary initialization and compiler warnings
Modified:
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java
incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java
Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java?view=diff&rev=440871&r1=440870&r2=440871
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java Wed Sep 6 14:08:44 2006
@@ -15,107 +15,116 @@
package org.apache.harmony.luni.internal.reflect;
-
class ProxyCharArrayCache {
- // to avoid using Enumerations, walk the individual tables skipping nulls
- char[] keyTable[];
-
- int valueTable[];
-
- int elementSize; // number of elements in the table
-
- int threshold;
-
- static boolean equals(char[] first, char[] second) {
- if (first == second) {
- return true;
- }
- if (first == null || second == null) {
- return false;
- }
- if (first.length != second.length) {
- return false;
- }
-
- for (int i = first.length; --i >= 0;)
- if (first[i] != second[i]) {
- return false;
- }
- return true;
- }
-
- ProxyCharArrayCache(int initialCapacity) {
- if (initialCapacity < 13) {
- initialCapacity = 13;
- }
- this.elementSize = 0;
- this.threshold = (int) (initialCapacity * 0.66f);
- this.keyTable = new char[initialCapacity][];
- this.valueTable = new int[initialCapacity];
- }
-
- int get(char[] key) {
- int index = hashCodeChar(key);
- while (keyTable[index] != null) {
- if (equals(keyTable[index], key))
- return valueTable[index];
- index = (index + 1) % keyTable.length;
- }
- return -1;
- }
-
- private int hashCodeChar(char[] val) {
- int length = val.length;
- int hash = 0;
- int n = 2; // number of characters skipped
- for (int i = 0; i < length; i += n)
- hash += val[i];
- return (hash & 0x7FFFFFFF) % keyTable.length;
- }
-
- int put(char[] key, int value) {
- int index = hashCodeChar(key);
- while (keyTable[index] != null) {
- if (equals(keyTable[index], key))
- return valueTable[index] = value;
- index = (index + 1) % keyTable.length;
- }
- keyTable[index] = key;
- valueTable[index] = value;
-
- // assumes the threshold is never equal to the size of the table
- if (++elementSize > threshold)
- rehash();
- return value;
- }
-
- private void rehash() {
- ProxyCharArrayCache newHashtable = new ProxyCharArrayCache(
- keyTable.length * 2);
- for (int i = keyTable.length; --i >= 0;)
- if (keyTable[i] != null)
- newHashtable.put(keyTable[i], valueTable[i]);
-
- this.keyTable = newHashtable.keyTable;
- this.valueTable = newHashtable.valueTable;
- this.threshold = newHashtable.threshold;
- }
-
- int size() {
- return elementSize;
- }
-
- public String toString() {
- int max = size();
- StringBuffer buf = new StringBuffer();
- buf.append("{");
- for (int i = 0; i < max; ++i) {
- if (keyTable[i] != null)
- buf.append(keyTable[i]).append("->").append(valueTable[i]);
- if (i < max)
- buf.append(", ");
- }
- buf.append("}");
- return buf.toString();
- }
+ static boolean equals(char[] first, char[] second) {
+ if (first == second) {
+ return true;
+ }
+ if (first == null || second == null) {
+ return false;
+ }
+ if (first.length != second.length) {
+ return false;
+ }
+
+ for (int i = first.length; --i >= 0;) {
+ if (first[i] != second[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // to avoid using Enumerations, walk the individual tables skipping nulls
+ private char[] keyTable[];
+
+ private int valueTable[];
+
+ // number of elements in the table
+ private int elementSize;
+
+ private int threshold;
+
+ ProxyCharArrayCache(int initialCapacity) {
+ if (initialCapacity < 13) {
+ initialCapacity = 13;
+ }
+ this.elementSize = 0;
+ this.threshold = (int) (initialCapacity * 0.66f);
+ this.keyTable = new char[initialCapacity][];
+ this.valueTable = new int[initialCapacity];
+ }
+
+ int get(char[] key) {
+ int index = hashCodeChar(key);
+ while (keyTable[index] != null) {
+ if (equals(keyTable[index], key)) {
+ return valueTable[index];
+ }
+ index = (index + 1) % keyTable.length;
+ }
+ return -1;
+ }
+
+ private int hashCodeChar(char[] val) {
+ int length = val.length;
+ int hash = 0;
+ int n = 2; // number of characters skipped
+ for (int i = 0; i < length; i += n) {
+ hash += val[i];
+ }
+ return (hash & 0x7FFFFFFF) % keyTable.length;
+ }
+
+ int put(char[] key, int value) {
+ int index = hashCodeChar(key);
+ while (keyTable[index] != null) {
+ if (equals(keyTable[index], key)) {
+ return valueTable[index] = value;
+ }
+ index = (index + 1) % keyTable.length;
+ }
+ keyTable[index] = key;
+ valueTable[index] = value;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++elementSize > threshold) {
+ rehash();
+ }
+ return value;
+ }
+
+ private void rehash() {
+ ProxyCharArrayCache newHashtable = new ProxyCharArrayCache(keyTable.length * 2);
+ for (int i = keyTable.length; --i >= 0;) {
+ if (keyTable[i] != null) {
+ newHashtable.put(keyTable[i], valueTable[i]);
+ }
+ }
+
+ this.keyTable = newHashtable.keyTable;
+ this.valueTable = newHashtable.valueTable;
+ this.threshold = newHashtable.threshold;
+ }
+
+ int size() {
+ return elementSize;
+ }
+
+ @Override
+ public String toString() {
+ int max = size();
+ StringBuilder buf = new StringBuilder();
+ buf.append("{");
+ for (int i = 0; i < max; ++i) {
+ if (keyTable[i] != null) {
+ buf.append(keyTable[i]).append("->").append(valueTable[i]);
+ }
+ if (i < max) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+ return buf.toString();
+ }
}
Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java?view=diff&rev=440871&r1=440870&r2=440871
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java Wed Sep 6 14:08:44 2006
@@ -15,7 +15,6 @@
package org.apache.harmony.luni.internal.reflect;
-
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
@@ -26,847 +25,894 @@
import java.util.HashSet;
public final class ProxyClassFile implements ProxyConstants {
- private ProxyConstantPool constantPool;
- byte[] header; // the header contains all the bytes till the end of the
- // constant pool
+ private static final int INITIAL_CONTENTS_SIZE = 1000;
- int headerOffset;
+ private static final int INITIAL_HEADER_SIZE = 500;
- private byte[] contents; // that collection contains all the remaining
- // bytes of the .class file
-
- private int contentsOffset;
-
- private int constantPoolOffset;
-
- private ProxyMethod[] proxyMethods;
-
- private static final int INITIAL_CONTENTS_SIZE = 1000;
-
- private static final int INITIAL_HEADER_SIZE = 500;
-
- private static final int INCREMENT_SIZE = 250;
-
- private static Method ObjectEqualsMethod, ObjectHashCodeMethod,
- ObjectToStringMethod;
-
- private static Method ClassForNameMethod, ClassGetMethod;
-
- private static Method HandlerInvokeMethod;
-
- private static Constructor ProxyConstructor,
- UndeclaredThrowableExceptionConstructor;
-
- private static Field ProxyHandlerField;
-
- public static byte[] generateBytes(String typeName, Class[] interfaces) {
- ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces);
- classFile.addFields();
- classFile.findMethods(interfaces);
- classFile.addMethods();
- classFile.addAttributes();
- return classFile.getBytes();
- }
-
- static char[] getConstantPoolName(Class c) {
- if (c.isArray())
- return c.getName().replace('.', '/').toCharArray(); // Array classes
- // are named
- // with their
- // signature
- if (c.isPrimitive()) {
- // Special cases for each base type.
- if (c == void.class)
- return new char[] { 'V' };
- if (c == int.class)
- return new char[] { 'I' };
- if (c == boolean.class)
- return new char[] { 'Z' };
- if (c == byte.class)
- return new char[] { 'B' };
- if (c == char.class)
- return new char[] { 'C' };
- if (c == short.class)
- return new char[] { 'S' };
- if (c == long.class)
- return new char[] { 'J' };
- if (c == float.class)
- return new char[] { 'F' };
- if (c == double.class)
- return new char[] { 'D' };
- }
- return ("L" + c.getName().replace('.', '/') + ";").toCharArray();
- }
-
- static char[] getConstantPoolName(Constructor method) /* (ILjava/lang/Thread;)V */{
- Class[] parameters = method.getParameterTypes();
- StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
- buffer.append('(');
- for (int i = 0, length = parameters.length; i < length; i++)
- buffer.append(getConstantPoolName(parameters[i]));
- buffer.append(')');
- buffer.append(getConstantPoolName(void.class));
- return buffer.toString().toCharArray();
- }
-
- static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
- Class[] parameters = method.getParameterTypes();
- StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
- buffer.append('(');
- for (int i = 0, length = parameters.length; i < length; i++)
- buffer.append(getConstantPoolName(parameters[i]));
- buffer.append(')');
- buffer.append(getConstantPoolName(method.getReturnType()));
- return buffer.toString().toCharArray();
- }
-
- ProxyClassFile(String typeName, Class[] interfaces) {
- header = new byte[INITIAL_HEADER_SIZE];
- // generate the magic numbers inside the header
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
- header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
- // Compatible with JDK 1.2
- header[headerOffset++] = 0;
- header[headerOffset++] = 0;
- header[headerOffset++] = 0;
- header[headerOffset++] = 46;
- constantPoolOffset = headerOffset;
- headerOffset += 2;
- constantPool = new ProxyConstantPool(this);
- contents = new byte[INITIAL_CONTENTS_SIZE];
- // now we continue to generate the bytes inside the contents array
- int accessFlags = AccPublic | AccFinal | AccSuper;
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- int classNameIndex = constantPool.typeIndex(typeName);
- contents[contentsOffset++] = (byte) (classNameIndex >> 8);
- contents[contentsOffset++] = (byte) classNameIndex;
- int superclassNameIndex = constantPool
- .typeIndex("java/lang/reflect/Proxy");
- contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
- contents[contentsOffset++] = (byte) superclassNameIndex;
- int interfacesCount = interfaces.length;
- contents[contentsOffset++] = (byte) (interfacesCount >> 8);
- contents[contentsOffset++] = (byte) interfacesCount;
- for (int i = 0; i < interfacesCount; i++) {
- int interfaceIndex = constantPool
- .typeIndex(interfaces[i].getName());
- contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
- contents[contentsOffset++] = (byte) interfaceIndex;
- }
- }
-
- private void addAttributes() {
- writeUnsignedShort(0); // classFile does not have attributes of its own
-
- // resynchronize all offsets of the classfile
- header = constantPool.poolContent;
- headerOffset = constantPool.currentOffset;
- int constantPoolCount = constantPool.currentIndex;
- header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
- header[constantPoolOffset] = (byte) constantPoolCount;
- }
-
- private void addFields() {
- writeUnsignedShort(0); // we have no fields
- }
-
- private void addMethods() {
- int methodCount = proxyMethods.length;
- writeUnsignedShort(methodCount + 1);
-
- // save constructor
- writeUnsignedShort(AccPublic);
- writeUnsignedShort(constantPool.literalIndex(Init));
- if (ProxyConstructor == null) {
- try {
- ProxyConstructor = Proxy.class
- .getDeclaredConstructor(new Class[] { InvocationHandler.class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool
- .literalIndex(getConstantPoolName(ProxyConstructor)));
- writeUnsignedShort(1); // store just the code attribute
- writeUnsignedShort(constantPool.literalIndex(CodeName));
- // save attribute_length(4), max_stack(2), max_locals(2), code_length(4)
- int codeLength = 6;
- writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2),
- // code_length(4), 2 zero shorts
- writeUnsignedShort(2);
- writeUnsignedShort(2);
- writeUnsignedWord(codeLength);
- writeUnsignedByte(OPC_aload_0);
- writeUnsignedByte(OPC_aload_1);
- writeUnsignedByte(OPC_invokespecial);
- writeUnsignedShort(constantPool.literalIndex(ProxyConstructor));
- writeUnsignedByte(OPC_return);
- writeUnsignedShort(0); // no exceptions table
- writeUnsignedShort(0); // there are no attributes for the code
- // attribute
-
- for (int i = 0; i < methodCount; i++) {
- ProxyMethod pMethod = proxyMethods[i];
- Method method = pMethod.method;
- writeUnsignedShort(AccPublic | AccFinal);
- writeUnsignedShort(constantPool.literalIndex(method.getName()
- .toCharArray()));
- writeUnsignedShort(constantPool
- .literalIndex(getConstantPoolName(method)));
- Class[] thrownsExceptions = pMethod.commonExceptions;
- int eLength = thrownsExceptions.length;
- if (eLength > 0) {
- writeUnsignedShort(2); // store the exception & code attributes
- // The method has a throw clause. So we need to add an exception
- // attribute
- writeUnsignedShort(constantPool.literalIndex(ExceptionsName));
- // The attribute length = length * 2 + 2 in case of a exception
- // attribute
- writeUnsignedWord(eLength * 2 + 2);
- writeUnsignedShort(eLength);
- for (int e = 0; e < eLength; e++)
- writeUnsignedShort(constantPool
- .typeIndex(thrownsExceptions[e].getName()));
- } else {
- writeUnsignedShort(1); // store just the code attribute
- }
- generateCodeAttribute(pMethod);
- }
- }
-
- private void findMethods(Class[] interfaces) {
- // find all methods defined by the interfaces (including inherited
- // interfaces) plus hashCode, equals & toString from Object
- // build an array with the methods... no duplicates - check upto the
- // array size when the interface's first method was added
- if (ObjectEqualsMethod == null) {
- try {
- ObjectEqualsMethod = Object.class.getMethod("equals",
- new Class[] { Object.class });
- ObjectHashCodeMethod = Object.class.getMethod("hashCode",
- new Class[0]);
- ObjectToStringMethod = Object.class.getMethod("toString",
- new Class[0]);
- } catch (NoSuchMethodException ex) {
- throw new InternalError();
- }
- }
-
- ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25);
- allMethods.add(new ProxyMethod(ObjectEqualsMethod));
- allMethods.add(new ProxyMethod(ObjectHashCodeMethod));
- allMethods.add(new ProxyMethod(ObjectToStringMethod));
-
- HashSet<Class> interfacesSeen = new HashSet<Class>();
- for (int i = 0, length = interfaces.length; i < length; i++)
- findMethods(interfaces[i], allMethods, interfacesSeen);
-
- proxyMethods = new ProxyMethod[allMethods.size()];
- allMethods.toArray(proxyMethods);
- }
-
- private void findMethods(Class nextInterface, ArrayList<ProxyMethod> allMethods,
- HashSet<Class> interfacesSeen) {
- // add the nextInterface's methods to allMethods
- // if an equivalent method already exists then return types must be
- // identical... don't replace it
-
- if (interfacesSeen.contains(nextInterface))
- return; // already walked it
- interfacesSeen.add(nextInterface);
-
- int existingMethodCount = allMethods.size();
- Method[] methods = nextInterface.getMethods();
- nextMethod: for (int i = 0, length = methods.length; i < length; i++) {
- Method method = methods[i];
- for (int j = 0; j < existingMethodCount; j++)
- if (allMethods.get(j).matchMethod(method))
- continue nextMethod;
- allMethods.add(new ProxyMethod(method));
- }
+ private static final int INCREMENT_SIZE = 250;
- Class[] superInterfaces = nextInterface.getInterfaces();
- for (int i = 0, length = superInterfaces.length; i < length; i++)
- // recursion should be minimal
- findMethods(superInterfaces[i], allMethods, interfacesSeen);
- }
+ private static Method ObjectEqualsMethod;;
- private void generateCodeAttribute(ProxyMethod pMethod) {
- int codeAttributeOffset = contentsOffset;
- int contentsLength = contents.length;
- if (contentsOffset + 20 + 100 >= contentsLength)
- System.arraycopy(contents, 0, (contents = new byte[contentsLength
- + INCREMENT_SIZE]), 0, contentsLength);
- writeUnsignedShort(constantPool.literalIndex(CodeName));
- // leave space for attribute_length(4), max_stack(2), max_locals(2),
- // code_length(4)
- contentsOffset += 12;
-
- /*
- * to push the args for the call to invoke push the receiver field h 0
- * aload0 1 getfield 33 java.lang.reflect.Proxy.h
- * Ljava.lang.reflect.InvocationHandler; push the receiver as the first
- * arg 4 aload0 push the method push the array of args call invoke 89
- * invokeinterface 67
- * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;
- * cast return result catch & convert exceptions if necessary
- */
-
- int codeStartOffset = contentsOffset;
- writeUnsignedByte(OPC_aload_0);
- writeUnsignedByte(OPC_getfield);
- if (ProxyHandlerField == null) {
- try {
- ProxyHandlerField = Proxy.class.getDeclaredField("h");
- } catch (NoSuchFieldException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField));
- writeUnsignedByte(OPC_aload_0);
- Method method = pMethod.method;
- Class[] argTypes = method.getParameterTypes();
- genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes);
- int maxLocals = genInvokeArgs(argTypes);
- writeUnsignedByte(OPC_invokeinterface);
- if (HandlerInvokeMethod == null) {
- try {
- HandlerInvokeMethod = InvocationHandler.class.getMethod(
- "invoke", new Class[] { Object.class, Method.class,
- Object[].class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool.literalIndex(HandlerInvokeMethod));
- writeUnsignedByte(4); // invoke has 3 args
- writeUnsignedByte(0); // 4th operand must be 0
- genCastReturnType(method.getReturnType());
- int codeLength = contentsOffset - codeStartOffset;
-
- Class[] checkedExceptions = pMethod.getCheckedExceptions();
- int checkedLength = checkedExceptions.length;
- if (checkedLength > 0) {
- int codeEndIndex = contentsOffset - codeStartOffset;
- writeUnsignedByte(OPC_athrow); // rethrow the caught exception
-
- genStoreArg(maxLocals);
- writeUnsignedByte(OPC_new);
- writeUnsignedShort(constantPool
- .typeIndex("java/lang/reflect/UndeclaredThrowableException"));
- writeUnsignedByte(OPC_dup);
- genLoadArg(maxLocals);
- maxLocals++; // now expecting the exception
- writeUnsignedByte(OPC_invokespecial);
- if (UndeclaredThrowableExceptionConstructor == null) {
- try {
- UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class
- .getConstructor(new Class[] { Throwable.class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool
- .literalIndex(UndeclaredThrowableExceptionConstructor));
- writeUnsignedByte(OPC_athrow);
-
- codeLength = contentsOffset - codeStartOffset;
-
- // write the exception table
- writeUnsignedShort(checkedLength + 1);
- for (int i = 0; i < checkedLength; i++) {
- writeUnsignedShort(0);
- writeUnsignedShort(codeEndIndex);
- writeUnsignedShort(codeEndIndex);
- writeUnsignedShort(constantPool.typeIndex(checkedExceptions[i]
- .getName()));
- }
- writeUnsignedShort(0);
- writeUnsignedShort(codeEndIndex);
- writeUnsignedShort(codeEndIndex + 1); // starts after the first
- // throw
- writeUnsignedShort(constantPool.typeIndex("java/lang/Throwable"));
- } else {
- writeUnsignedShort(0); // no exceptions table
- }
-
- writeUnsignedShort(0); // there are no attributes for the code
- // attribute
-
- // Complete the creation of the code attribute by setting the
- // attribute_length, max_stack
- // max_locals, code_length & exception table
- // codeAttributeOffset is the position inside contents byte array before
- // we started to write
- // That means that to write the attribute_length you need to offset by 2
- // the value of codeAttributeOffset
- // to get the right position, 6 for the max_stack etc...
- int codeAttributeLength = contentsOffset - (codeAttributeOffset + 6);
- contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-
- int maxStack = maxLocals + 10; // larger than the exact amount
- contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8);
- contents[codeAttributeOffset + 7] = (byte) maxStack;
- contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8);
- contents[codeAttributeOffset + 9] = (byte) maxLocals;
- contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24);
- contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16);
- contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8);
- contents[codeAttributeOffset + 13] = (byte) codeLength;
- }
-
- /*
- * Perform call to Class.getMethod(String, Class[]) receiver 13 ldc 37
- * (java.lang.String) "java.lang.Object" 15 invokestatic 43
- * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; selector 37
- * ldc 55 (java.lang.String) "equals" plus method args 39 iconst0 40
- * anewarray 39 java.lang.Class or 39 iconst1 40 anewarray 39
- * java.lang.Class 43 dup 44 iconst0 53 ldc 37 (java.lang.String)
- * "java.lang.Object" 55 invokestatic 43
- * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; 77 aastore
- * or 39 iconst2 40 anewarray 39 java.lang.Class 43 dup 44 iconst0 45
- * getstatic 102 java.lang.Integer.TYPE Ljava.lang.Class; 48 aastore 49 dup
- * 50 iconst1 51 getstatic 104 java.lang.Boolean.TYPE Ljava.lang.Class; 54
- * aastore then 78 invokevirtual 59
- * java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;
- */
- private void genCallGetMethod(Class receiverType, String selector,
- Class[] argTypes) {
- genCallClassForName(receiverType.getName());
- writeLdc(selector);
- int length = argTypes.length;
- writeIntConstant(length);
- writeUnsignedByte(OPC_anewarray);
- writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
- for (int i = 0; i < length; i++) {
- writeUnsignedByte(OPC_dup);
- writeIntConstant(i);
- Class type = argTypes[i];
- if (type.isPrimitive()) {
- writeUnsignedByte(OPC_getstatic);
- writeUnsignedShort(constantPool.literalIndex(typeField(type)));
- } else {
- genCallClassForName(type.getName());
- }
- writeUnsignedByte(OPC_aastore);
- }
- writeUnsignedByte(OPC_invokevirtual);
- if (ClassGetMethod == null) {
- try {
- ClassGetMethod = Class.class.getMethod("getMethod",
- new Class[] { String.class, Class[].class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
- }
-
- /*
- * Add argument array for call to InvocationHandler.invoke
- *
- * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86
- * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61
- * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68
- * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73
- * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80
- * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore
- */
- private int genInvokeArgs(Class[] argTypes) {
- int argByteOffset = 1; // remember h is at position 0
- int length = argTypes.length;
- if (length == 0) {
- writeUnsignedByte(OPC_aconst_null);
- } else {
- writeIntConstant(length);
- writeUnsignedByte(OPC_anewarray);
- writeUnsignedShort(constantPool.typeIndex("java/lang/Object"));
- for (int i = 0; i < length; i++) {
- writeUnsignedByte(OPC_dup);
- writeIntConstant(i);
- argByteOffset = genInvokeArg(argTypes[i], argByteOffset);
- writeUnsignedByte(OPC_aastore);
- }
- }
- return argByteOffset;
- }
-
- private int genInvokeArg(Class type, int argByteOffset) {
- // offset represents maxLocals in bytes
- if (type.isPrimitive()) {
- writeUnsignedByte(OPC_new);
- writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type)));
- writeUnsignedByte(OPC_dup);
- if (argByteOffset > 255)
- writeUnsignedByte(OPC_wide);
- if (type == long.class) {
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_lload_0);
- break;
- case 1:
- writeUnsignedByte(OPC_lload_1);
- break;
- case 2:
- writeUnsignedByte(OPC_lload_2);
- break;
- case 3:
- writeUnsignedByte(OPC_lload_3);
- break;
- default:
- writeUnsignedByte(OPC_lload);
- if (argByteOffset > 255)
- writeUnsignedShort(argByteOffset);
- else
- writeUnsignedByte(argByteOffset);
- }
- argByteOffset += 2;
- } else if (type == float.class) {
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_fload_0);
- break;
- case 1:
- writeUnsignedByte(OPC_fload_1);
- break;
- case 2:
- writeUnsignedByte(OPC_fload_2);
- break;
- case 3:
- writeUnsignedByte(OPC_fload_3);
- break;
- default:
- writeUnsignedByte(OPC_fload);
- if (argByteOffset > 255)
- writeUnsignedShort(argByteOffset);
- else
- writeUnsignedByte(argByteOffset);
- }
- argByteOffset++;
- } else if (type == double.class) {
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_dload_0);
- break;
- case 1:
- writeUnsignedByte(OPC_dload_1);
- break;
- case 2:
- writeUnsignedByte(OPC_dload_2);
- break;
- case 3:
- writeUnsignedByte(OPC_dload_3);
- break;
- default:
- writeUnsignedByte(OPC_dload);
- if (argByteOffset > 255)
- writeUnsignedShort(argByteOffset);
- else
- writeUnsignedByte(argByteOffset);
- }
- argByteOffset += 2;
- } else { // handles int, short, byte, boolean & char
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_iload_0);
- break;
- case 1:
- writeUnsignedByte(OPC_iload_1);
- break;
- case 2:
- writeUnsignedByte(OPC_iload_2);
- break;
- case 3:
- writeUnsignedByte(OPC_iload_3);
- break;
- default:
- writeUnsignedByte(OPC_iload);
- if (argByteOffset > 255)
- writeUnsignedShort(argByteOffset);
- else
- writeUnsignedByte(argByteOffset);
- }
- argByteOffset++;
- }
- writeUnsignedByte(OPC_invokespecial);
- writeUnsignedShort(constantPool.literalIndex(typeInitMethod(type)));
- } else {
- genLoadArg(argByteOffset);
- argByteOffset++;
- }
- return argByteOffset;
- }
-
- /*
- * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73
- * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91
- * java.lang.String 55 areturn
- */
- private void genCastReturnType(Class type) {
- if (type.isPrimitive()) {
- if (type == void.class) {
- writeUnsignedByte(OPC_pop);
- writeUnsignedByte(OPC_return);
- } else {
- writeUnsignedByte(OPC_checkcast);
- writeUnsignedShort(constantPool
- .typeIndex(typeWrapperName(type)));
- writeUnsignedByte(OPC_invokevirtual);
- writeUnsignedShort(constantPool
- .literalIndex(typeAccessMethod(type)));
- if (type == long.class) {
- writeUnsignedByte(OPC_lreturn);
- } else if (type == float.class) {
- writeUnsignedByte(OPC_freturn);
- } else if (type == double.class) {
- writeUnsignedByte(OPC_dreturn);
- } else { // handles int, short, byte, boolean & char
- writeUnsignedByte(OPC_ireturn);
- }
- }
- } else {
- writeUnsignedByte(OPC_checkcast);
- writeUnsignedShort(constantPool.typeIndex(type.getName()));
- writeUnsignedByte(OPC_areturn);
- }
- }
-
- private void genCallClassForName(String typeName) {
- writeLdc(typeName);
- writeUnsignedByte(OPC_invokestatic);
- if (ClassForNameMethod == null) {
- try {
- ClassForNameMethod = Class.class.getMethod("forName",
- new Class[] { String.class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- }
- writeUnsignedShort(constantPool.literalIndex(ClassForNameMethod));
- }
-
- private void genLoadArg(int argByteOffset) {
- if (argByteOffset > 255) {
- writeUnsignedByte(OPC_wide);
- writeUnsignedByte(OPC_aload);
- writeUnsignedShort(argByteOffset);
- } else {
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_aload_0);
- break;
- case 1:
- writeUnsignedByte(OPC_aload_1);
- break;
- case 2:
- writeUnsignedByte(OPC_aload_2);
- break;
- case 3:
- writeUnsignedByte(OPC_aload_3);
- break;
- default:
- writeUnsignedByte(OPC_aload);
- writeUnsignedByte(argByteOffset);
- }
- }
- }
-
- private void genStoreArg(int argByteOffset) {
- if (argByteOffset > 255) {
- writeUnsignedByte(OPC_wide);
- writeUnsignedByte(OPC_astore);
- writeUnsignedShort(argByteOffset);
- } else {
- switch (argByteOffset) {
- case 0:
- writeUnsignedByte(OPC_astore_0);
- break;
- case 1:
- writeUnsignedByte(OPC_astore_1);
- break;
- case 2:
- writeUnsignedByte(OPC_astore_2);
- break;
- case 3:
- writeUnsignedByte(OPC_astore_3);
- break;
- default:
- writeUnsignedByte(OPC_astore);
- writeUnsignedByte(argByteOffset);
- }
- }
- }
-
- private byte[] getBytes() {
- byte[] fullContents = new byte[headerOffset + contentsOffset];
- System.arraycopy(header, 0, fullContents, 0, headerOffset);
- System.arraycopy(contents, 0, fullContents, headerOffset,
- contentsOffset);
- return fullContents;
- }
-
- private Method typeAccessMethod(Class baseType) {
- try {
- if (baseType == int.class)
- return Integer.class.getMethod("intValue", (Class[])null);
- if (baseType == short.class)
- return Short.class.getMethod("shortValue", (Class[])null);
- if (baseType == byte.class)
- return Byte.class.getMethod("byteValue", (Class[])null);
- if (baseType == boolean.class)
- return Boolean.class.getMethod("booleanValue", (Class[])null);
- if (baseType == char.class)
- return Character.class.getMethod("charValue", (Class[])null);
- if (baseType == long.class)
- return Long.class.getMethod("longValue", (Class[])null);
- if (baseType == float.class)
- return Float.class.getMethod("floatValue", (Class[])null);
- if (baseType == double.class)
- return Double.class.getMethod("doubleValue", (Class[])null);
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- return null;
- }
-
- private Field typeField(Class baseType) {
- try {
- if (baseType == int.class)
- return Integer.class.getField("TYPE");
- if (baseType == short.class)
- return Short.class.getField("TYPE");
- if (baseType == byte.class)
- return Byte.class.getField("TYPE");
- if (baseType == boolean.class)
- return Boolean.class.getField("TYPE");
- if (baseType == char.class)
- return Character.class.getField("TYPE");
- if (baseType == long.class)
- return Long.class.getField("TYPE");
- if (baseType == float.class)
- return Float.class.getField("TYPE");
- if (baseType == double.class)
- return Double.class.getField("TYPE");
- } catch (NoSuchFieldException e) {
- throw new InternalError();
- }
- return null;
- }
-
- private Constructor typeInitMethod(Class baseType) {
- try {
- if (baseType == int.class)
- return Integer.class.getConstructor(new Class[] { int.class });
- if (baseType == short.class)
- return Short.class.getConstructor(new Class[] { short.class });
- if (baseType == byte.class)
- return Byte.class.getConstructor(new Class[] { byte.class });
- if (baseType == boolean.class)
- return Boolean.class
- .getConstructor(new Class[] { boolean.class });
- if (baseType == char.class)
- return Character.class
- .getConstructor(new Class[] { char.class });
- if (baseType == long.class)
- return Long.class.getConstructor(new Class[] { long.class });
- if (baseType == float.class)
- return Float.class.getConstructor(new Class[] { float.class });
- if (baseType == double.class)
- return Double.class
- .getConstructor(new Class[] { double.class });
- } catch (NoSuchMethodException e) {
- throw new InternalError();
- }
- return null;
- }
-
- private String typeWrapperName(Class baseType) {
- if (baseType == int.class)
- return "java/lang/Integer";
- if (baseType == short.class)
- return "java/lang/Short";
- if (baseType == byte.class)
- return "java/lang/Byte";
- if (baseType == boolean.class)
- return "java/lang/Boolean";
- if (baseType == char.class)
- return "java/lang/Character";
- if (baseType == long.class)
- return "java/lang/Long";
- if (baseType == float.class)
- return "java/lang/Float";
- if (baseType == double.class)
- return "java/lang/Double";
- return null;
- }
-
- private void writeIntConstant(int b) {
- switch (b) {
- case 0:
- writeUnsignedByte(OPC_iconst_0);
- break;
- case 1:
- writeUnsignedByte(OPC_iconst_1);
- break;
- case 2:
- writeUnsignedByte(OPC_iconst_2);
- break;
- case 3:
- writeUnsignedByte(OPC_iconst_3);
- break;
- case 4:
- writeUnsignedByte(OPC_iconst_4);
- break;
- case 5:
- writeUnsignedByte(OPC_iconst_5);
- break;
- default:
- writeUnsignedByte(OPC_bipush);
- writeUnsignedByte(b);
- }
- }
-
- private void writeLdc(String constant) {
- int index = constantPool.literalIndexForLdc(constant.toCharArray());
- if (index <= 0)
- throw new InternalError();
- if (index > 255) {
- writeUnsignedByte(OPC_ldc_w);
- writeUnsignedShort(index);
- } else {
- writeUnsignedByte(OPC_ldc);
- writeUnsignedByte(index);
- }
- }
-
- private void writeUnsignedByte(int b) {
- try {
- contents[contentsOffset++] = (byte) b;
- } catch (IndexOutOfBoundsException e) {
- int actualLength = contents.length;
- System.arraycopy(contents, 0, (contents = new byte[actualLength
- + INCREMENT_SIZE]), 0, actualLength);
- contents[contentsOffset - 1] = (byte) b;
- }
- }
-
- private void writeUnsignedShort(int b) {
- writeUnsignedByte(b >>> 8);
- writeUnsignedByte(b);
- }
-
- private void writeUnsignedWord(int b) {
- writeUnsignedByte(b >>> 24);
- writeUnsignedByte(b >>> 16);
- writeUnsignedByte(b >>> 8);
- writeUnsignedByte(b);
- }
+ private static Method ObjectHashCodeMethod;
+
+ private static Method ObjectToStringMethod;
+
+ private static Method ClassForNameMethod;
+
+ private static Method ClassGetMethod;
+
+ private static Method HandlerInvokeMethod;
+
+ private static Constructor<?> ProxyConstructor;
+
+ private static Constructor<?> UndeclaredThrowableExceptionConstructor;
+
+ private static Field ProxyHandlerField;
+
+ public static byte[] generateBytes(String typeName, Class[] interfaces) {
+ ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces);
+ classFile.addFields();
+ classFile.findMethods(interfaces);
+ classFile.addMethods();
+ classFile.addAttributes();
+ return classFile.getBytes();
+ }
+
+ static char[] getConstantPoolName(Class<?> c) {
+ if (c.isArray()) {
+ // Array classes are named/ with their signature
+ return c.getName().replace('.', '/').toCharArray();
+ }
+
+ if (c.isPrimitive()) {
+ // Special cases for each base type.
+ if (c == void.class) {
+ return new char[] { 'V' };
+ }
+ if (c == int.class) {
+ return new char[] { 'I' };
+ }
+ if (c == boolean.class) {
+ return new char[] { 'Z' };
+ }
+ if (c == byte.class) {
+ return new char[] { 'B' };
+ }
+ if (c == char.class) {
+ return new char[] { 'C' };
+ }
+ if (c == short.class) {
+ return new char[] { 'S' };
+ }
+ if (c == long.class) {
+ return new char[] { 'J' };
+ }
+ if (c == float.class) {
+ return new char[] { 'F' };
+ }
+ if (c == double.class) {
+ return new char[] { 'D' };
+ }
+ }
+ return ("L" + c.getName().replace('.', '/') + ";").toCharArray();
+ }
+
+ static char[] getConstantPoolName(Constructor<?> method) /* (ILjava/lang/Thread;)V */{
+ Class[] parameters = method.getParameterTypes();
+ StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
+ buffer.append('(');
+ for (Class<?> element : parameters) {
+ buffer.append(getConstantPoolName(element));
+ }
+ buffer.append(')');
+ buffer.append(getConstantPoolName(void.class));
+ return buffer.toString().toCharArray();
+ }
+
+ static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
+ Class[] parameters = method.getParameterTypes();
+ StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
+ buffer.append('(');
+ for (Class<?> element : parameters) {
+ buffer.append(getConstantPoolName(element));
+ }
+ buffer.append(')');
+ buffer.append(getConstantPoolName(method.getReturnType()));
+ return buffer.toString().toCharArray();
+ }
+
+ private ProxyConstantPool constantPool;
+
+ // the header contains all the bytes till the end of the constant pool
+ byte[] header;
+
+ int headerOffset;
+
+ // that collection contains all the remaining bytes of the .class file
+ private byte[] contents;
+
+ private int contentsOffset;
+
+ private int constantPoolOffset;
+
+ private ProxyMethod[] proxyMethods;
+
+ ProxyClassFile(String typeName, Class[] interfaces) {
+ super();
+ header = new byte[INITIAL_HEADER_SIZE];
+ // generate the magic numbers inside the header
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+ // Compatible with JDK 1.2
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 46;
+ constantPoolOffset = headerOffset;
+ headerOffset += 2;
+ constantPool = new ProxyConstantPool(this);
+ contents = new byte[INITIAL_CONTENTS_SIZE];
+ // now we continue to generate the bytes inside the contents array
+ int accessFlags = AccPublic | AccFinal | AccSuper;
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ int classNameIndex = constantPool.typeIndex(typeName);
+ contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+ contents[contentsOffset++] = (byte) classNameIndex;
+ int superclassNameIndex = constantPool.typeIndex("java/lang/reflect/Proxy");
+ contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
+ contents[contentsOffset++] = (byte) superclassNameIndex;
+ int interfacesCount = interfaces.length;
+ contents[contentsOffset++] = (byte) (interfacesCount >> 8);
+ contents[contentsOffset++] = (byte) interfacesCount;
+ for (int i = 0; i < interfacesCount; i++) {
+ int interfaceIndex = constantPool.typeIndex(interfaces[i].getName());
+ contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+ contents[contentsOffset++] = (byte) interfaceIndex;
+ }
+ }
+
+ private void addAttributes() {
+ writeUnsignedShort(0); // classFile does not have attributes of its own
+
+ // resynchronize all offsets of the classfile
+ header = constantPool.poolContent;
+ headerOffset = constantPool.currentOffset;
+ int constantPoolCount = constantPool.currentIndex;
+ header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+ header[constantPoolOffset] = (byte) constantPoolCount;
+ }
+
+ private void addFields() {
+ writeUnsignedShort(0); // we have no fields
+ }
+
+ private void addMethods() {
+ int methodCount = proxyMethods.length;
+ writeUnsignedShort(methodCount + 1);
+
+ // save constructor
+ writeUnsignedShort(AccPublic);
+ writeUnsignedShort(constantPool.literalIndex(Init));
+ if (ProxyConstructor == null) {
+ try {
+ ProxyConstructor = Proxy.class
+ .getDeclaredConstructor(new Class[] { InvocationHandler.class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool.literalIndex(getConstantPoolName(ProxyConstructor)));
+ writeUnsignedShort(1); // store just the code attribute
+ writeUnsignedShort(constantPool.literalIndex(CodeName));
+ // save attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+ int codeLength = 6;
+ writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2),
+ // code_length(4), 2 zero shorts
+ writeUnsignedShort(2);
+ writeUnsignedShort(2);
+ writeUnsignedWord(codeLength);
+ writeUnsignedByte(OPC_aload_0);
+ writeUnsignedByte(OPC_aload_1);
+ writeUnsignedByte(OPC_invokespecial);
+ writeUnsignedShort(constantPool.literalIndex(ProxyConstructor));
+ writeUnsignedByte(OPC_return);
+ writeUnsignedShort(0); // no exceptions table
+ writeUnsignedShort(0); // there are no attributes for the code
+ // attribute
+
+ for (int i = 0; i < methodCount; i++) {
+ ProxyMethod pMethod = proxyMethods[i];
+ Method method = pMethod.method;
+ writeUnsignedShort(AccPublic | AccFinal);
+ writeUnsignedShort(constantPool.literalIndex(method.getName().toCharArray()));
+ writeUnsignedShort(constantPool.literalIndex(getConstantPoolName(method)));
+ Class[] thrownsExceptions = pMethod.commonExceptions;
+ int eLength = thrownsExceptions.length;
+ if (eLength > 0) {
+ writeUnsignedShort(2); // store the exception & code attributes
+ // The method has a throw clause. So we need to add an exception
+ // attribute
+ writeUnsignedShort(constantPool.literalIndex(ExceptionsName));
+ // The attribute length = length * 2 + 2 in case of a exception
+ // attribute
+ writeUnsignedWord(eLength * 2 + 2);
+ writeUnsignedShort(eLength);
+ for (int e = 0; e < eLength; e++) {
+ writeUnsignedShort(constantPool.typeIndex(thrownsExceptions[e].getName()));
+ }
+ } else {
+ writeUnsignedShort(1); // store just the code attribute
+ }
+ generateCodeAttribute(pMethod);
+ }
+ }
+
+ private void findMethods(Class[] interfaces) {
+ /*
+ * find all methods defined by the interfaces (including inherited
+ * interfaces) plus hashCode, equals & toString from Object build an
+ * array with the methods... no duplicates - check up to the array size
+ * when the interface's first method was added
+ */
+ if (ObjectEqualsMethod == null) {
+ try {
+ ObjectEqualsMethod = Object.class.getMethod("equals",
+ new Class[] { Object.class });
+ ObjectHashCodeMethod = Object.class.getMethod("hashCode", new Class[0]);
+ ObjectToStringMethod = Object.class.getMethod("toString", new Class[0]);
+ } catch (NoSuchMethodException ex) {
+ throw new InternalError();
+ }
+ }
+
+ ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25);
+ allMethods.add(new ProxyMethod(ObjectEqualsMethod));
+ allMethods.add(new ProxyMethod(ObjectHashCodeMethod));
+ allMethods.add(new ProxyMethod(ObjectToStringMethod));
+
+ HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>();
+ for (Class<?> element : interfaces) {
+ findMethods(element, allMethods, interfacesSeen);
+ }
+
+ proxyMethods = new ProxyMethod[allMethods.size()];
+ allMethods.toArray(proxyMethods);
+ }
+
+ private void findMethods(Class<?> nextInterface, ArrayList<ProxyMethod> allMethods,
+ HashSet<Class<?>> interfacesSeen) {
+ /*
+ * add the nextInterface's methods to allMethods if an equivalent method
+ * already exists then return types must be identical... don't replace
+ * it
+ */
+ if (interfacesSeen.contains(nextInterface)) {
+ return; // already walked it
+ }
+ interfacesSeen.add(nextInterface);
+
+ int existingMethodCount = allMethods.size();
+ Method[] methods = nextInterface.getMethods();
+ nextMethod: for (Method method : methods) {
+ for (int j = 0; j < existingMethodCount; j++) {
+ if (allMethods.get(j).matchMethod(method)) {
+ continue nextMethod;
+ }
+ }
+ allMethods.add(new ProxyMethod(method));
+ }
+ Class<?>[] superInterfaces = nextInterface.getInterfaces();
+ for (Class<?> element : superInterfaces) {
+ // recursion should be minimal
+ findMethods(element, allMethods, interfacesSeen);
+ }
+ }
+
+ private void generateCodeAttribute(ProxyMethod pMethod) {
+ int codeAttributeOffset = contentsOffset;
+ int contentsLength = contents.length;
+ if (contentsOffset + 20 + 100 >= contentsLength) {
+ System.arraycopy(contents, 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]), 0, contentsLength);
+ }
+ writeUnsignedShort(constantPool.literalIndex(CodeName));
+ // leave space for attribute_length(4), max_stack(2), max_locals(2),
+ // code_length(4)
+ contentsOffset += 12;
+
+ /*
+ * to push the args for the call to invoke push the receiver field h 0
+ * aload0 1 getfield 33 java.lang.reflect.Proxy.h
+ * Ljava.lang.reflect.InvocationHandler; push the receiver as the first
+ * arg 4 aload0 push the method push the array of args call invoke 89
+ * invokeinterface 67
+ * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;
+ * cast return result catch & convert exceptions if necessary
+ */
+
+ int codeStartOffset = contentsOffset;
+ writeUnsignedByte(OPC_aload_0);
+ writeUnsignedByte(OPC_getfield);
+ if (ProxyHandlerField == null) {
+ try {
+ ProxyHandlerField = Proxy.class.getDeclaredField("h");
+ } catch (NoSuchFieldException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField));
+ writeUnsignedByte(OPC_aload_0);
+ Method method = pMethod.method;
+ Class[] argTypes = method.getParameterTypes();
+ genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes);
+ int maxLocals = genInvokeArgs(argTypes);
+ writeUnsignedByte(OPC_invokeinterface);
+ if (HandlerInvokeMethod == null) {
+ try {
+ HandlerInvokeMethod = InvocationHandler.class.getMethod("invoke", new Class[] {
+ Object.class, Method.class, Object[].class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool.literalIndex(HandlerInvokeMethod));
+ writeUnsignedByte(4); // invoke has 3 args
+ writeUnsignedByte(0); // 4th operand must be 0
+ genCastReturnType(method.getReturnType());
+ int codeLength = contentsOffset - codeStartOffset;
+
+ Class[] checkedExceptions = pMethod.getCheckedExceptions();
+ int checkedLength = checkedExceptions.length;
+ if (checkedLength > 0) {
+ int codeEndIndex = contentsOffset - codeStartOffset;
+ writeUnsignedByte(OPC_athrow); // re-throw the caught exception
+
+ genStoreArg(maxLocals);
+ writeUnsignedByte(OPC_new);
+ writeUnsignedShort(constantPool
+ .typeIndex("java/lang/reflect/UndeclaredThrowableException"));
+ writeUnsignedByte(OPC_dup);
+ genLoadArg(maxLocals);
+ maxLocals++; // now expecting the exception
+ writeUnsignedByte(OPC_invokespecial);
+ if (UndeclaredThrowableExceptionConstructor == null) {
+ try {
+ UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class
+ .getConstructor(new Class[] { Throwable.class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool
+ .literalIndex(UndeclaredThrowableExceptionConstructor));
+ writeUnsignedByte(OPC_athrow);
+
+ codeLength = contentsOffset - codeStartOffset;
+
+ // write the exception table
+ writeUnsignedShort(checkedLength + 1);
+ for (int i = 0; i < checkedLength; i++) {
+ writeUnsignedShort(0);
+ writeUnsignedShort(codeEndIndex);
+ writeUnsignedShort(codeEndIndex);
+ writeUnsignedShort(constantPool.typeIndex(checkedExceptions[i].getName()));
+ }
+ writeUnsignedShort(0);
+ writeUnsignedShort(codeEndIndex);
+ writeUnsignedShort(codeEndIndex + 1); // starts after the first
+ // throw
+ writeUnsignedShort(constantPool.typeIndex("java/lang/Throwable"));
+ } else {
+ writeUnsignedShort(0); // no exceptions table
+ }
+ // there are no attributes for the code attribute
+ writeUnsignedShort(0);
+
+ /*
+ * Complete the creation of the code attribute by setting the
+ * attribute_length, max_stack max_locals, code_length & exception table
+ * codeAttributeOffset is the position inside contents byte array before
+ * we started to write That means that to write the attribute_length you
+ * need to offset by 2 the value of codeAttributeOffset to get the right
+ * position, 6 for the max_stack etc...
+ */
+ int codeAttributeLength = contentsOffset - (codeAttributeOffset + 6);
+ contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+
+ int maxStack = maxLocals + 10; // larger than the exact amount
+ contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8);
+ contents[codeAttributeOffset + 7] = (byte) maxStack;
+ contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8);
+ contents[codeAttributeOffset + 9] = (byte) maxLocals;
+ contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24);
+ contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16);
+ contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8);
+ contents[codeAttributeOffset + 13] = (byte) codeLength;
+ }
+
+ /**
+ * Perform call to Class.getMethod(String, Class[]) receiver 13 ldc 37
+ * (java.lang.String) "java.lang.Object" 15 invokestatic 43
+ * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; selector 37
+ * ldc 55 (java.lang.String) "equals" plus method args 39 iconst0 40
+ * anewarray 39 java.lang.Class or 39 iconst1 40 anewarray 39
+ * java.lang.Class 43 dup 44 iconst0 53 ldc 37 (java.lang.String)
+ * "java.lang.Object" 55 invokestatic 43
+ * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; 77 aastore
+ * or 39 iconst2 40 anewarray 39 java.lang.Class 43 dup 44 iconst0 45
+ * getstatic 102 java.lang.Integer.TYPE Ljava.lang.Class; 48 aastore 49 dup
+ * 50 iconst1 51 getstatic 104 java.lang.Boolean.TYPE Ljava.lang.Class; 54
+ * aastore then 78 invokevirtual 59
+ * java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;
+ */
+ private void genCallGetMethod(Class<?> receiverType, String selector, Class[] argTypes) {
+ genCallClassForName(receiverType.getName());
+ writeLdc(selector);
+ int length = argTypes.length;
+ writeIntConstant(length);
+ writeUnsignedByte(OPC_anewarray);
+ writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
+ for (int i = 0; i < length; i++) {
+ writeUnsignedByte(OPC_dup);
+ writeIntConstant(i);
+ Class<?> type = argTypes[i];
+ if (type.isPrimitive()) {
+ writeUnsignedByte(OPC_getstatic);
+ writeUnsignedShort(constantPool.literalIndex(typeField(type)));
+ } else {
+ genCallClassForName(type.getName());
+ }
+ writeUnsignedByte(OPC_aastore);
+ }
+ writeUnsignedByte(OPC_invokevirtual);
+ if (ClassGetMethod == null) {
+ try {
+ ClassGetMethod = Class.class.getMethod("getMethod", new Class[] { String.class,
+ Class[].class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
+ }
+
+ /**
+ * Add argument array for call to InvocationHandler.invoke
+ *
+ * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86
+ * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61
+ * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68
+ * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73
+ * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80
+ * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore
+ */
+ private int genInvokeArgs(Class[] argTypes) {
+ int argByteOffset = 1; // remember h is at position 0
+ int length = argTypes.length;
+ if (length == 0) {
+ writeUnsignedByte(OPC_aconst_null);
+ } else {
+ writeIntConstant(length);
+ writeUnsignedByte(OPC_anewarray);
+ writeUnsignedShort(constantPool.typeIndex("java/lang/Object"));
+ for (int i = 0; i < length; i++) {
+ writeUnsignedByte(OPC_dup);
+ writeIntConstant(i);
+ argByteOffset = genInvokeArg(argTypes[i], argByteOffset);
+ writeUnsignedByte(OPC_aastore);
+ }
+ }
+ return argByteOffset;
+ }
+
+ private int genInvokeArg(Class<?> type, int argByteOffset) {
+ // offset represents maxLocals in bytes
+ if (type.isPrimitive()) {
+ writeUnsignedByte(OPC_new);
+ writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type)));
+ writeUnsignedByte(OPC_dup);
+ if (argByteOffset > 255) {
+ writeUnsignedByte(OPC_wide);
+ }
+ if (type == long.class) {
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_lload_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_lload_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_lload_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_lload_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_lload);
+ if (argByteOffset > 255) {
+ writeUnsignedShort(argByteOffset);
+ } else {
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ argByteOffset += 2;
+ } else if (type == float.class) {
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_fload_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_fload_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_fload_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_fload_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_fload);
+ if (argByteOffset > 255) {
+ writeUnsignedShort(argByteOffset);
+ } else {
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ argByteOffset++;
+ } else if (type == double.class) {
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_dload_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_dload_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_dload_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_dload_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_dload);
+ if (argByteOffset > 255) {
+ writeUnsignedShort(argByteOffset);
+ } else {
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ argByteOffset += 2;
+ } else { // handles int, short, byte, boolean & char
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_iload_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_iload_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_iload_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_iload_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_iload);
+ if (argByteOffset > 255) {
+ writeUnsignedShort(argByteOffset);
+ } else {
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ argByteOffset++;
+ }
+ writeUnsignedByte(OPC_invokespecial);
+ writeUnsignedShort(constantPool.literalIndex(typeInitMethod(type)));
+ } else {
+ genLoadArg(argByteOffset);
+ argByteOffset++;
+ }
+ return argByteOffset;
+ }
+
+ /**
+ * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73
+ * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91
+ * java.lang.String 55 areturn
+ */
+ private void genCastReturnType(Class<?> type) {
+ if (type.isPrimitive()) {
+ if (type == void.class) {
+ writeUnsignedByte(OPC_pop);
+ writeUnsignedByte(OPC_return);
+ } else {
+ writeUnsignedByte(OPC_checkcast);
+ writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type)));
+ writeUnsignedByte(OPC_invokevirtual);
+ writeUnsignedShort(constantPool.literalIndex(typeAccessMethod(type)));
+ if (type == long.class) {
+ writeUnsignedByte(OPC_lreturn);
+ } else if (type == float.class) {
+ writeUnsignedByte(OPC_freturn);
+ } else if (type == double.class) {
+ writeUnsignedByte(OPC_dreturn);
+ } else { // handles int, short, byte, boolean & char
+ writeUnsignedByte(OPC_ireturn);
+ }
+ }
+ } else {
+ writeUnsignedByte(OPC_checkcast);
+ writeUnsignedShort(constantPool.typeIndex(type.getName()));
+ writeUnsignedByte(OPC_areturn);
+ }
+ }
+
+ private void genCallClassForName(String typeName) {
+ writeLdc(typeName);
+ writeUnsignedByte(OPC_invokestatic);
+ if (ClassForNameMethod == null) {
+ try {
+ ClassForNameMethod = Class.class.getMethod("forName",
+ new Class[] { String.class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedShort(constantPool.literalIndex(ClassForNameMethod));
+ }
+
+ private void genLoadArg(int argByteOffset) {
+ if (argByteOffset > 255) {
+ writeUnsignedByte(OPC_wide);
+ writeUnsignedByte(OPC_aload);
+ writeUnsignedShort(argByteOffset);
+ } else {
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_aload_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_aload_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_aload_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_aload_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_aload);
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ }
+
+ private void genStoreArg(int argByteOffset) {
+ if (argByteOffset > 255) {
+ writeUnsignedByte(OPC_wide);
+ writeUnsignedByte(OPC_astore);
+ writeUnsignedShort(argByteOffset);
+ } else {
+ switch (argByteOffset) {
+ case 0:
+ writeUnsignedByte(OPC_astore_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_astore_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_astore_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_astore_3);
+ break;
+ default:
+ writeUnsignedByte(OPC_astore);
+ writeUnsignedByte(argByteOffset);
+ }
+ }
+ }
+
+ private byte[] getBytes() {
+ byte[] fullContents = new byte[headerOffset + contentsOffset];
+ System.arraycopy(header, 0, fullContents, 0, headerOffset);
+ System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
+ return fullContents;
+ }
+
+ private Method typeAccessMethod(Class<?> baseType) {
+ try {
+ if (baseType == int.class) {
+ return Integer.class.getMethod("intValue", (Class[]) null);
+ }
+ if (baseType == short.class) {
+ return Short.class.getMethod("shortValue", (Class[]) null);
+ }
+ if (baseType == byte.class) {
+ return Byte.class.getMethod("byteValue", (Class[]) null);
+ }
+ if (baseType == boolean.class) {
+ return Boolean.class.getMethod("booleanValue", (Class[]) null);
+ }
+ if (baseType == char.class) {
+ return Character.class.getMethod("charValue", (Class[]) null);
+ }
+ if (baseType == long.class) {
+ return Long.class.getMethod("longValue", (Class[]) null);
+ }
+ if (baseType == float.class) {
+ return Float.class.getMethod("floatValue", (Class[]) null);
+ }
+ if (baseType == double.class) {
+ return Double.class.getMethod("doubleValue", (Class[]) null);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ return null;
+ }
+
+ private Field typeField(Class<?> baseType) {
+ try {
+ if (baseType == int.class) {
+ return Integer.class.getField("TYPE");
+ }
+ if (baseType == short.class) {
+ return Short.class.getField("TYPE");
+ }
+ if (baseType == byte.class) {
+ return Byte.class.getField("TYPE");
+ }
+ if (baseType == boolean.class) {
+ return Boolean.class.getField("TYPE");
+ }
+ if (baseType == char.class) {
+ return Character.class.getField("TYPE");
+ }
+ if (baseType == long.class) {
+ return Long.class.getField("TYPE");
+ }
+ if (baseType == float.class) {
+ return Float.class.getField("TYPE");
+ }
+ if (baseType == double.class) {
+ return Double.class.getField("TYPE");
+ }
+ } catch (NoSuchFieldException e) {
+ throw new InternalError();
+ }
+ return null;
+ }
+
+ private Constructor<?> typeInitMethod(Class<?> baseType) {
+ try {
+ if (baseType == int.class) {
+ return Integer.class.getConstructor(new Class[] { int.class });
+ }
+ if (baseType == short.class) {
+ return Short.class.getConstructor(new Class[] { short.class });
+ }
+ if (baseType == byte.class) {
+ return Byte.class.getConstructor(new Class[] { byte.class });
+ }
+ if (baseType == boolean.class) {
+ return Boolean.class.getConstructor(new Class[] { boolean.class });
+ }
+ if (baseType == char.class) {
+ return Character.class.getConstructor(new Class[] { char.class });
+ }
+ if (baseType == long.class) {
+ return Long.class.getConstructor(new Class[] { long.class });
+ }
+ if (baseType == float.class) {
+ return Float.class.getConstructor(new Class[] { float.class });
+ }
+ if (baseType == double.class) {
+ return Double.class.getConstructor(new Class[] { double.class });
+ }
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ return null;
+ }
+
+ private String typeWrapperName(Class<?> baseType) {
+ if (baseType == int.class) {
+ return "java/lang/Integer";
+ }
+ if (baseType == short.class) {
+ return "java/lang/Short";
+ }
+ if (baseType == byte.class) {
+ return "java/lang/Byte";
+ }
+ if (baseType == boolean.class) {
+ return "java/lang/Boolean";
+ }
+ if (baseType == char.class) {
+ return "java/lang/Character";
+ }
+ if (baseType == long.class) {
+ return "java/lang/Long";
+ }
+ if (baseType == float.class) {
+ return "java/lang/Float";
+ }
+ if (baseType == double.class) {
+ return "java/lang/Double";
+ }
+ return null;
+ }
+
+ private void writeIntConstant(int b) {
+ switch (b) {
+ case 0:
+ writeUnsignedByte(OPC_iconst_0);
+ break;
+ case 1:
+ writeUnsignedByte(OPC_iconst_1);
+ break;
+ case 2:
+ writeUnsignedByte(OPC_iconst_2);
+ break;
+ case 3:
+ writeUnsignedByte(OPC_iconst_3);
+ break;
+ case 4:
+ writeUnsignedByte(OPC_iconst_4);
+ break;
+ case 5:
+ writeUnsignedByte(OPC_iconst_5);
+ break;
+ default:
+ writeUnsignedByte(OPC_bipush);
+ writeUnsignedByte(b);
+ }
+ }
+
+ private void writeLdc(String constant) {
+ int index = constantPool.literalIndexForLdc(constant.toCharArray());
+ if (index <= 0) {
+ throw new InternalError();
+ }
+ if (index > 255) {
+ writeUnsignedByte(OPC_ldc_w);
+ writeUnsignedShort(index);
+ } else {
+ writeUnsignedByte(OPC_ldc);
+ writeUnsignedByte(index);
+ }
+ }
+
+ private void writeUnsignedByte(int b) {
+ try {
+ contents[contentsOffset++] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ int actualLength = contents.length;
+ System.arraycopy(contents, 0, (contents = new byte[actualLength + INCREMENT_SIZE]),
+ 0, actualLength);
+ contents[contentsOffset - 1] = (byte) b;
+ }
+ }
+
+ private void writeUnsignedShort(int b) {
+ writeUnsignedByte(b >>> 8);
+ writeUnsignedByte(b);
+ }
+
+ private void writeUnsignedWord(int b) {
+ writeUnsignedByte(b >>> 24);
+ writeUnsignedByte(b >>> 16);
+ writeUnsignedByte(b >>> 8);
+ writeUnsignedByte(b);
+ }
}
Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java?view=diff&rev=440871&r1=440870&r2=440871
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java Wed Sep 6 14:08:44 2006
@@ -39,7 +39,7 @@
public static final int CONSTANTPOOL_GROW_SIZE = 1000;
- public ProxyCharArrayCache UTF8Cache;
+ ProxyCharArrayCache UTF8Cache;
ProxyCharArrayCache stringCache;
@@ -53,11 +53,11 @@
ProxyNameAndTypeCache nameAndTypeCache;
- public byte[] poolContent;
+ byte[] poolContent;
- public int currentIndex;
+ int currentIndex;
- public int currentOffset;
+ int currentOffset;
ProxyConstantPool(ProxyClassFile classFile) {
UTF8Cache = new ProxyCharArrayCache(UTF8_INITIAL_SIZE);
@@ -136,7 +136,7 @@
return index;
}
- int literalIndex(Constructor aMethod) {
+ int literalIndex(Constructor<?> aMethod) {
int index;
if ((index = methodCache.get(aMethod)) < 0) {
int classIndex = typeIndex(aMethod.getDeclaringClass().getName());
Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java?view=diff&rev=440871&r1=440870&r2=440871
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java Wed Sep 6 14:08:44 2006
@@ -15,98 +15,106 @@
package org.apache.harmony.luni.internal.reflect;
-
import java.lang.reflect.Method;
+import org.apache.harmony.luni.util.Msg;
+
class ProxyMethod {
- Method method;
+ Method method;
- Class[] commonExceptions;
+ Class[] commonExceptions;
- ProxyMethod(Method method) {
- this.method = method;
- this.commonExceptions = method.getExceptionTypes();
- }
-
- Class[] getCheckedExceptions() {
- Class[] newExceptions = (Class[]) commonExceptions.clone();
- int cLength = newExceptions.length;
- for (int c = 0, cL = cLength; c < cL; c++) {
- Class ex = newExceptions[c];
- if (Throwable.class == ex)
- return new Class[0]; // if Throwable is included then treat
- // as if no exceptions are checked
- if (Error.class.isAssignableFrom(ex)
- || RuntimeException.class.isAssignableFrom(ex)) {
- newExceptions[c] = null;
- cLength--;
- }
- }
-
- // All errors & runtime exceptions are passed back without being
- // wrappered
- Class[] result = new Class[cLength + 2];
- int index = 0;
- result[index++] = Error.class;
- result[index++] = RuntimeException.class;
- for (int i = 0, length = newExceptions.length; i < length; i++) {
- Class ex = newExceptions[i];
- if (ex != null)
- result[index++] = ex;
- }
- return result;
- }
-
- boolean matchMethod(Method otherMethod) {
- if (!method.getName().equals(otherMethod.getName()))
- return false;
-
- Class[] params1 = method.getParameterTypes();
- Class[] params2 = otherMethod.getParameterTypes();
- int p = params1.length;
- if (p != params2.length)
- return false;
- while (--p >= 0)
- if (params1[p] != params2[p])
- return false;
-
- if (method.getReturnType() != otherMethod.getReturnType())
- throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg.getString(
- "K00f2", method.getName()));
- if (commonExceptions.length != 0) {
- Class[] otherExceptions = otherMethod.getExceptionTypes();
- if (otherExceptions.length == 0) {
- commonExceptions = otherExceptions;
- } else {
- int cLength = commonExceptions.length;
- nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) {
- Class<?> cException = commonExceptions[c];
- for (int o = 0; o < oL; o++) {
- Class<?> oException = otherExceptions[o];
- if (cException == oException)
- continue nextException;
- if (oException.isAssignableFrom(cException))
- continue nextException; // cException is a subclass
- if (cException.isAssignableFrom(oException)) {
- // oException is a subclass, keep it instead
- commonExceptions[c] = cException = oException;
- continue nextException;
- }
- }
- commonExceptions[c] = null;
- cLength--;
- }
- if (cLength != commonExceptions.length) {
- Class[] newExceptions = new Class[cLength];
- for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) {
- Class ex = commonExceptions[i];
- if (ex != null)
- newExceptions[j++] = ex;
- }
- commonExceptions = newExceptions;
- }
- }
- }
- return true;
- }
+ ProxyMethod(Method method) {
+ this.method = method;
+ this.commonExceptions = method.getExceptionTypes();
+ }
+
+ Class[] getCheckedExceptions() {
+ Class[] newExceptions = commonExceptions.clone();
+ int cLength = newExceptions.length;
+ for (int c = 0, cL = cLength; c < cL; c++) {
+ Class<?> ex = newExceptions[c];
+ if (Throwable.class == ex) {
+ // if Throwable is included then treat as if no exceptions are
+ // checked
+ return new Class[0];
+ }
+ if (Error.class.isAssignableFrom(ex) || RuntimeException.class.isAssignableFrom(ex)) {
+ newExceptions[c] = null;
+ cLength--;
+ }
+ }
+
+ // All errors & runtime exceptions are passed back without being wrapped
+ Class[] result = new Class[cLength + 2];
+ int index = 0;
+ result[index++] = Error.class;
+ result[index++] = RuntimeException.class;
+ for (Class<?> ex : newExceptions) {
+ if (ex != null) {
+ result[index++] = ex;
+ }
+ }
+ return result;
+ }
+
+ boolean matchMethod(Method otherMethod) {
+ if (!method.getName().equals(otherMethod.getName())) {
+ return false;
+ }
+
+ Class[] params1 = method.getParameterTypes();
+ Class[] params2 = otherMethod.getParameterTypes();
+ int p = params1.length;
+ if (p != params2.length) {
+ return false;
+ }
+ while (--p >= 0) {
+ if (params1[p] != params2[p]) {
+ return false;
+ }
+ }
+
+ if (method.getReturnType() != otherMethod.getReturnType()) {
+ throw new IllegalArgumentException(Msg.getString("K00f2", method.getName()));
+ }
+ if (commonExceptions.length != 0) {
+ Class[] otherExceptions = otherMethod.getExceptionTypes();
+ if (otherExceptions.length == 0) {
+ commonExceptions = otherExceptions;
+ } else {
+ int cLength = commonExceptions.length;
+ nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) {
+ Class<?> cException = commonExceptions[c];
+ for (int o = 0; o < oL; o++) {
+ Class<?> oException = otherExceptions[o];
+ if (cException == oException) {
+ continue nextException;
+ }
+ if (oException.isAssignableFrom(cException)) {
+ continue nextException; // cException is a subclass
+ }
+ if (cException.isAssignableFrom(oException)) {
+ // oException is a subclass, keep it instead
+ commonExceptions[c] = cException = oException;
+ continue nextException;
+ }
+ }
+ commonExceptions[c] = null;
+ cLength--;
+ }
+ if (cLength != commonExceptions.length) {
+ Class[] newExceptions = new Class[cLength];
+ for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) {
+ Class<?> ex = commonExceptions[i];
+ if (ex != null) {
+ newExceptions[j++] = ex;
+ }
+ }
+ commonExceptions = newExceptions;
+ }
+ }
+ }
+ return true;
+ }
}