You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ap...@apache.org on 2008/01/24 22:37:22 UTC
svn commit: r615010 - in
/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect:
ProxyClassFile.java ProxyConstantPool.java ProxyMethod.java
Author: apetrenko
Date: Thu Jan 24 13:37:20 2008
New Revision: 615010
URL: http://svn.apache.org/viewvc?rev=615010&view=rev
Log:
Patch for HARMONY-5404 "[classlib][luni][reflection][performance]Proxy
instances can be optimized"
Modified:
harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java?rev=615010&r1=615009&r2=615010&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java Thu Jan 24 13:37:20 2008
@@ -17,6 +17,7 @@
package org.apache.harmony.luni.internal.reflect;
+import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
@@ -38,9 +39,7 @@
private static Method ObjectHashCodeMethod;
- private static Method ObjectToStringMethod;
-
- private static Method ClassForNameMethod;
+ private static Method ObjectToStringMethod;
private static Method ClassGetMethod;
@@ -54,8 +53,8 @@
public static byte[] generateBytes(String typeName, Class[] interfaces) {
ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces);
- classFile.addFields();
classFile.findMethods(interfaces);
+ classFile.addFields();
classFile.addMethods();
classFile.addAttributes();
return classFile.getBytes();
@@ -139,9 +138,12 @@
private int constantPoolOffset;
private ProxyMethod[] proxyMethods;
+
+ private String typeName;
ProxyClassFile(String typeName, Class[] interfaces) {
super();
+ this.typeName = typeName;
header = new byte[INITIAL_HEADER_SIZE];
// generate the magic numbers inside the header
header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
@@ -152,7 +154,7 @@
header[headerOffset++] = 0;
header[headerOffset++] = 0;
header[headerOffset++] = 0;
- header[headerOffset++] = 46;
+ header[headerOffset++] = 49;
constantPoolOffset = headerOffset;
headerOffset += 2;
constantPool = new ProxyConstantPool(this);
@@ -190,14 +192,119 @@
header[constantPoolOffset] = (byte) constantPoolCount;
}
- private void addFields() {
- writeUnsignedShort(0); // we have no fields
+ private void writeStaticInitializer() {
+ writeUnsignedShort(AccStatic);
+ writeUnsignedShort(constantPool.literalIndex(new char[] {'<', 'c', 'l', 'i', 'n', 'i', 't', '>'}));
+ writeUnsignedShort(constantPool.literalIndex(new char[]{'(', ')','V'}));
+ writeUnsignedShort(1); //todo add Exceptions
+ generateCodeAttribute3();
+ }
+
+ private void completeCodeDescription(int codeLength, int offset, int maxLocals) {
+ writeUnsignedWord(codeLength + 8, offset);
+ writeUnsignedShort(maxLocals + 10, offset + 4);
+ writeUnsignedShort(maxLocals, offset + 6);
+ writeUnsignedWord(codeLength - 12, offset + 8);
+ }
+
+ private void initializeField(ProxyMethod m, int index) {
+ String methodName = m.method.getName();
+ Class[] params = m.method.getParameterTypes();
+ int paramLengths = params.length;
+ writeLdcWithClass(m.getDeclaringClass().getName());
+ writeLdc(methodName);
+ writeIntConstant(paramLengths);
+ writeUnsignedByte(OPC_anewarray);
+ writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
+ for (int i = 0; i < paramLengths; i++) {
+ writeUnsignedByte(OPC_dup);
+ writeIntConstant(i);
+ if (params[i].isPrimitive()) {
+ writeUnsignedByte(OPC_getstatic);
+ writeUnsignedShort(constantPool.literalIndex(typeWrapperName(params[i]),
+ "TYPE", Class.class));
+
+ } else {
+ writeLdcWithClass(params[i].getName());
+ }
+ writeUnsignedByte(OPC_aastore);
+ }
+
+ if (ClassGetMethod == null) {
+ try {
+ ClassGetMethod = Class.class.getMethod("getMethod",
+ new Class[] { String.class, Class[].class });
+ } catch (NoSuchMethodException e) {
+ throw new InternalError();
+ }
+ }
+ writeUnsignedByte(OPC_invokevirtual);
+ writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
+ writeUnsignedByte(OPC_putstatic);
+ writeUnsignedShort(constantPool.literalIndex(typeName,
+ getFieldNamebyMethodName(methodName, index),
+ Method.class));
+ }
+
+ private void generateCodeAttribute3() {
+ writeUnsignedShort(constantPool.literalIndex(CodeName));
+ int codeStart = contentsOffset;
+ writeUnsignedWord(0); //skip these fields so far
+ writeUnsignedWord(0);
+ writeUnsignedWord(0);
+ for (int i = 0; i < proxyMethods.length; i ++) {
+ initializeField(proxyMethods[i], i);
+ }
+ int gotoTarget = contentsOffset;
+ writeUnsignedByte(OPC_goto);
+ int targetForGotoOffset = contentsOffset;
+ writeUnsignedShort(4); //to be updated
+ int handlerStart = contentsOffset - codeStart - 12;
+ generateExceptionHandler();
+ gotoTarget = contentsOffset - gotoTarget;
+ writeUnsignedByte(OPC_return);
+ writeUnsignedShort(gotoTarget, targetForGotoOffset);
+ completeCodeDescription(contentsOffset - codeStart, codeStart, 1);
+ writeUnsignedShort(1);
+ writeUnsignedShort(0);
+ writeUnsignedShort(handlerStart);
+ writeUnsignedShort(handlerStart);
+ writeUnsignedShort(constantPool.typeIndex("java/lang/Exception"));
+ writeUnsignedShort(0); // there are no attributes for the code
+ }
+
+ //return handlerStart
+ private void generateExceptionHandler() {
+ //writeUnsignedByte(OPC_astore_0);
+ writeUnsignedByte(OPC_astore_0);
+ writeUnsignedByte(OPC_aload_0);
+
+ writeUnsignedByte(OPC_getstatic);
+ writeUnsignedShort(constantPool.literalIndex("java/lang/System",
+ "err",
+ PrintStream.class));
+ Method m = null;
+ try {
+ m = Exception.class.getMethod("printStackTrace", new Class[] {PrintStream.class});
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ }
+
+ writeUnsignedByte(OPC_invokevirtual);
+ writeUnsignedShort(constantPool.literalIndex(m));
+ }
+
+
+ private String getFieldNamebyMethodName(String methodName, int index) {
+ return methodName + "Method" + index;
}
+
private void addMethods() {
int methodCount = proxyMethods.length;
- writeUnsignedShort(methodCount + 1);
-
+ writeUnsignedShort(methodCount + 2);
+
+
// save constructor
writeUnsignedShort(AccPublic);
writeUnsignedShort(constantPool.literalIndex(Init));
@@ -228,15 +335,15 @@
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)));
+ writeUnsignedShort(constantPool.literalIndex(method.getName().toCharArray()));
+ writeUnsignedShort(constantPool.literalIndex(getConstantPoolName(method)));
+
Class[] thrownsExceptions = pMethod.commonExceptions;
int eLength = thrownsExceptions.length;
if (eLength > 0) {
@@ -255,8 +362,10 @@
} else {
writeUnsignedShort(1); // store just the code attribute
}
- generateCodeAttribute(pMethod);
+ generateCodeAttribute(pMethod, i);
}
+
+ writeStaticInitializer();
}
private void findMethods(Class[] interfaces) {
@@ -280,9 +389,9 @@
}
ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25);
- allMethods.add(new ProxyMethod(ObjectEqualsMethod));
- allMethods.add(new ProxyMethod(ObjectHashCodeMethod));
- allMethods.add(new ProxyMethod(ObjectToStringMethod));
+ allMethods.add(new ProxyMethod(Object.class, ObjectEqualsMethod));
+ allMethods.add(new ProxyMethod(Object.class, ObjectHashCodeMethod));
+ allMethods.add(new ProxyMethod(Object.class, ObjectToStringMethod));
HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>();
for (Class<?> element : interfaces) {
@@ -293,7 +402,20 @@
allMethods.toArray(proxyMethods);
}
- private void findMethods(Class<?> nextInterface,
+ private void addFields() {
+ //writeUnsignedShort(0); // we have no fields
+ int methodCount = proxyMethods.length;
+ writeUnsignedShort(methodCount);
+ for (int i = 0; i < methodCount; i ++) {
+ writeUnsignedShort(AccPublic | AccStatic);
+ String methodName = getFieldNamebyMethodName(proxyMethods[i].method.getName(), i);
+ writeUnsignedShort(constantPool.literalIndex(methodName.toCharArray()));
+ writeUnsignedShort(constantPool.literalIndex("Ljava/lang/reflect/Method;".toCharArray()));
+ writeUnsignedShort(0);
+ }
+ }
+
+ private void findMethods(Class<?> nextInterface,
ArrayList<ProxyMethod> allMethods, HashSet<Class<?>> interfacesSeen) {
/*
* add the nextInterface's methods to allMethods if an equivalent method
@@ -313,7 +435,7 @@
continue nextMethod;
}
}
- allMethods.add(new ProxyMethod(method));
+ allMethods.add(new ProxyMethod(nextInterface, method));
}
Class<?>[] superInterfaces = nextInterface.getInterfaces();
@@ -323,7 +445,7 @@
}
}
- private void generateCodeAttribute(ProxyMethod pMethod) {
+ private void generateCodeAttribute(ProxyMethod pMethod, int index) {
int codeAttributeOffset = contentsOffset;
int contentsLength = contents.length;
if (contentsOffset + 20 + 100 >= contentsLength) {
@@ -359,7 +481,9 @@
writeUnsignedByte(OPC_aload_0);
Method method = pMethod.method;
Class[] argTypes = method.getParameterTypes();
- genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes);
+ writeUnsignedByte(OPC_getstatic);
+ writeUnsignedShort(constantPool.literalIndex(typeName,
+ getFieldNamebyMethodName(pMethod.method.getName(), index),Method.class));
int maxLocals = genInvokeArgs(argTypes);
writeUnsignedByte(OPC_invokeinterface);
if (HandlerInvokeMethod == null) {
@@ -450,52 +574,7 @@
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
@@ -669,21 +748,7 @@
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) {
@@ -911,6 +976,20 @@
writeUnsignedByte(index);
}
}
+
+ private void writeLdcWithClass(String name) {
+ int index = constantPool.typeIndex(name);
+ 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 {
@@ -921,7 +1000,7 @@
+ INCREMENT_SIZE]), 0, actualLength);
contents[contentsOffset - 1] = (byte) b;
}
- }
+ }
private void writeUnsignedShort(int b) {
writeUnsignedByte(b >>> 8);
@@ -934,4 +1013,28 @@
writeUnsignedByte(b >>> 8);
writeUnsignedByte(b);
}
+
+ private void writeUnsignedByte(int b, int offset) {
+ try {
+ contents[offset] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ int actualLength = contents.length;
+ System.arraycopy(contents, 0, (contents = new byte[actualLength
+ + INCREMENT_SIZE]), 0, actualLength);
+ contents[offset - 1] = (byte) b;
+ }
+ }
+
+ private void writeUnsignedShort(int b, int offset) {
+ writeUnsignedByte(b >>> 8, offset);
+ writeUnsignedByte(b, offset + 1);
+ }
+
+ private void writeUnsignedWord(int b, int offset) {
+ writeUnsignedByte(b >>> 24, offset);
+ writeUnsignedByte(b >>> 16, offset + 1);
+ writeUnsignedByte(b >>> 8, offset + 2);
+ writeUnsignedByte(b, offset + 3);
+ }
+
}
Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java?rev=615010&r1=615009&r2=615010&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java Thu Jan 24 13:37:20 2008
@@ -121,23 +121,27 @@
}
return index;
}
-
- int literalIndex(Field aField) {
+
+ int literalIndex(Field aField) {
+ return literalIndex(aField.getDeclaringClass().getName(), aField.getName(), aField.getType());
+ }
+
+ int literalIndex(String declaringClass, String name, Class clazz) {
int index;
- if ((index = fieldCache.get(aField)) < 0) {
- int classIndex = typeIndex(aField.getDeclaringClass().getName());
+ String key = declaringClass + "." + name;
+ if ((index = fieldCache.get(key)) < 0) {
+ int classIndex = typeIndex(declaringClass);
int nameAndTypeIndex = literalIndexForNameAndType(
- literalIndex(aField.getName().toCharArray()),
- literalIndex(ProxyClassFile.getConstantPoolName(aField
- .getType())));
- index = fieldCache.put(aField, currentIndex++);
+ literalIndex(name.toCharArray()),
+ literalIndex(ProxyClassFile.getConstantPoolName(clazz)));
+ index = fieldCache.put(key, currentIndex++);
writeU1(FieldRefTag);
writeU2(classIndex);
writeU2(nameAndTypeIndex);
}
return index;
- }
-
+ }
+
int literalIndex(Constructor<?> aMethod) {
int index;
if ((index = methodCache.get(aMethod)) < 0) {
@@ -251,7 +255,7 @@
return index;
}
- private int literalIndexForNameAndType(int nameIndex, int typeIndex) {
+ int literalIndexForNameAndType(int nameIndex, int typeIndex) {
int index;
int[] key = new int[] { nameIndex, typeIndex };
if ((index = nameAndTypeCache.get(key)) == -1) {
Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java?rev=615010&r1=615009&r2=615010&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java Thu Jan 24 13:37:20 2008
@@ -23,10 +23,12 @@
class ProxyMethod {
Method method;
+ Class declaringClass;
Class[] commonExceptions;
- ProxyMethod(Method method) {
+ ProxyMethod(Class declaringClass, Method method) {
+ this.declaringClass = declaringClass;
this.method = method;
this.commonExceptions = method.getExceptionTypes();
}
@@ -127,6 +129,10 @@
}
}
return true;
+ }
+
+ Class getDeclaringClass() {
+ return declaringClass;
}
}