pax_global_header00006660000000000000000000000064121057563350014521gustar00rootroot0000000000000052 comment=17a696512e09ca9d3a223ffccb0ae91d818239b4 libreflectasm-java-1.05/000077500000000000000000000000001210575633500152015ustar00rootroot00000000000000libreflectasm-java-1.05/java/000077500000000000000000000000001210575633500161225ustar00rootroot00000000000000libreflectasm-java-1.05/java/.classpath000066400000000000000000000006571210575633500201150ustar00rootroot00000000000000 libreflectasm-java-1.05/java/.project000066400000000000000000000006021210575633500175670ustar00rootroot00000000000000 reflectasm org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature libreflectasm-java-1.05/java/license.txt000066400000000000000000000027311210575633500203100ustar00rootroot00000000000000Copyright (c) 2008, Nathan Sweet All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libreflectasm-java-1.05/java/pom.xml000066400000000000000000000037251210575633500174460ustar00rootroot00000000000000 4.0.0 com.esotericsoftware.reflectasm reflectasm 1.05 jar ReflectASM High performance Java reflection using code generation http://code.google.com/p/reflectasm/ New BSD License http://www.opensource.org/licenses/bsd-license.php repo http://reflectasm.googlecode.com/svn/ scm:svn:http://reflectasm.googlecode.com/svn/ nathan.sweet Nathan Sweet nathan.sweet@gmail.com UTF-8 org.ow2.asm asm 4.0 junit junit 4.8.2 test src test maven-resources-plugin 2.5 default-resources none default-testResources none libreflectasm-java-1.05/java/project.yaml000066400000000000000000000001011210575633500204440ustar00rootroot00000000000000version: 1.05 --- Build.build(project); Build.oneJAR(project);libreflectasm-java-1.05/java/src/000077500000000000000000000000001210575633500167115ustar00rootroot00000000000000libreflectasm-java-1.05/java/src/com/000077500000000000000000000000001210575633500174675ustar00rootroot00000000000000libreflectasm-java-1.05/java/src/com/esotericsoftware/000077500000000000000000000000001210575633500230575ustar00rootroot00000000000000libreflectasm-java-1.05/java/src/com/esotericsoftware/reflectasm/000077500000000000000000000000001210575633500252045ustar00rootroot00000000000000libreflectasm-java-1.05/java/src/com/esotericsoftware/reflectasm/AccessClassLoader.java000066400000000000000000000037301210575633500313700ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import java.lang.reflect.Method; import java.util.ArrayList; class AccessClassLoader extends ClassLoader { static private final ArrayList accessClassLoaders = new ArrayList(); static AccessClassLoader get (Class type) { ClassLoader parent = type.getClassLoader(); synchronized (accessClassLoaders) { for (int i = 0, n = accessClassLoaders.size(); i < n; i++) { AccessClassLoader accessClassLoader = accessClassLoaders.get(i); if (accessClassLoader.getParent() == parent) return accessClassLoader; } AccessClassLoader accessClassLoader = new AccessClassLoader(parent); accessClassLoaders.add(accessClassLoader); return accessClassLoader; } } private AccessClassLoader (ClassLoader parent) { super(parent); } protected synchronized java.lang.Class loadClass (String name, boolean resolve) throws ClassNotFoundException { // These classes come from the classloader that loaded AccessClassLoader. if (name.equals(FieldAccess.class.getName())) return FieldAccess.class; if (name.equals(MethodAccess.class.getName())) return MethodAccess.class; if (name.equals(ConstructorAccess.class.getName())) return ConstructorAccess.class; // All other classes come from the classloader that loaded the type we are accessing. return super.loadClass(name, resolve); } Class defineClass (String name, byte[] bytes) throws ClassFormatError { try { // Attempt to load the access class in the same loader, which makes protected and default access members accessible. Method method = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] {String.class, byte[].class, int.class, int.class}); method.setAccessible(true); return (Class)method.invoke(getParent(), new Object[] {name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length)}); } catch (Exception ignored) { } return defineClass(name, bytes, 0, bytes.length); } } libreflectasm-java-1.05/java/src/com/esotericsoftware/reflectasm/ConstructorAccess.java000066400000000000000000000046671210575633500315330ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import java.lang.reflect.Modifier; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import static org.objectweb.asm.Opcodes.*; public abstract class ConstructorAccess { static public ConstructorAccess get (Class type) { try { type.getConstructor((Class[])null); } catch (Exception ex) { if (type.isMemberClass() && !Modifier.isStatic(type.getModifiers())) throw new RuntimeException("Class cannot be created (non-static member class): " + type.getName()); else throw new RuntimeException("Class cannot be created (missing no-arg constructor): " + type.getName()); } AccessClassLoader loader = AccessClassLoader.get(type); String className = type.getName(); String accessClassName = className + "ConstructorAccess"; if (accessClassName.startsWith("java.")) accessClassName = "reflectasm." + accessClassName; Class accessClass = null; try { accessClass = loader.loadClass(accessClassName); } catch (ClassNotFoundException ignored) { } if (accessClass == null) { String accessClassNameInternal = accessClassName.replace('.', '/'); String classNameInternal = className.replace('.', '/'); ClassWriter cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null, "com/esotericsoftware/reflectasm/ConstructorAccess", null); MethodVisitor mv; { mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "com/esotericsoftware/reflectasm/ConstructorAccess", "", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "newInstance", "()Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitTypeInsn(NEW, classNameInternal); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "", "()V"); mv.visitInsn(ARETURN); mv.visitMaxs(2, 1); mv.visitEnd(); } cw.visitEnd(); byte[] data = cw.toByteArray(); accessClass = loader.defineClass(accessClassName, data); } try { return (ConstructorAccess)accessClass.newInstance(); } catch (Exception ex) { throw new RuntimeException("Error constructing constructor access class: " + accessClassName, ex); } } abstract public T newInstance (); } libreflectasm-java-1.05/java/src/com/esotericsoftware/reflectasm/FieldAccess.java000066400000000000000000000473571210575633500302340ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import static org.objectweb.asm.Opcodes.*; public abstract class FieldAccess { private String[] fieldNames; public int getIndex (String fieldName) { for (int i = 0, n = fieldNames.length; i < n; i++) if (fieldNames[i].equals(fieldName)) return i; throw new IllegalArgumentException("Unable to find public field: " + fieldName); } public void set (Object instance, String fieldName, Object value) { set(instance, getIndex(fieldName), value); } public Object get (Object instance, String fieldName) { return get(instance, getIndex(fieldName)); } public String[] getFieldNames () { return fieldNames; } abstract public void set (Object instance, int fieldIndex, Object value); abstract public void setBoolean (Object instance, int fieldIndex, boolean value); abstract public void setByte (Object instance, int fieldIndex, byte value); abstract public void setShort (Object instance, int fieldIndex, short value); abstract public void setInt (Object instance, int fieldIndex, int value); abstract public void setLong (Object instance, int fieldIndex, long value); abstract public void setDouble (Object instance, int fieldIndex, double value); abstract public void setFloat (Object instance, int fieldIndex, float value); abstract public void setChar (Object instance, int fieldIndex, char value); abstract public Object get (Object instance, int fieldIndex); abstract public String getString (Object instance, int fieldIndex); abstract public char getChar (Object instance, int fieldIndex); abstract public boolean getBoolean (Object instance, int fieldIndex); abstract public byte getByte (Object instance, int fieldIndex); abstract public short getShort (Object instance, int fieldIndex); abstract public int getInt (Object instance, int fieldIndex); abstract public long getLong (Object instance, int fieldIndex); abstract public double getDouble (Object instance, int fieldIndex); abstract public float getFloat (Object instance, int fieldIndex); static public FieldAccess get (Class type) { AccessClassLoader loader = AccessClassLoader.get(type); ArrayList fields = new ArrayList(); Class nextClass = type; while (nextClass != Object.class) { Field[] declaredFields = nextClass.getDeclaredFields(); for (int i = 0, n = declaredFields.length; i < n; i++) { Field field = declaredFields[i]; int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers)) continue; if (Modifier.isPrivate(modifiers)) continue; fields.add(field); } nextClass = nextClass.getSuperclass(); } String[] fieldNames = new String[fields.size()]; for (int i = 0, n = fieldNames.length; i < n; i++) fieldNames[i] = fields.get(i).getName(); String className = type.getName(); String accessClassName = className + "FieldAccess"; if (accessClassName.startsWith("java.")) accessClassName = "reflectasm." + accessClassName; Class accessClass = null; try { accessClass = loader.loadClass(accessClassName); } catch (ClassNotFoundException ignored) { } if (accessClass == null) { String accessClassNameInternal = accessClassName.replace('.', '/'); String classNameInternal = className.replace('.', '/'); ClassWriter cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null, "com/esotericsoftware/reflectasm/FieldAccess", null); insertConstructor(cw); insertGetObject(cw, classNameInternal, fields); insertSetObject(cw, classNameInternal, fields); insertGetPrimitive(cw, classNameInternal, fields, Type.BOOLEAN_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.BOOLEAN_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.BYTE_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.BYTE_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.SHORT_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.SHORT_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.INT_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.INT_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.LONG_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.LONG_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.DOUBLE_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.DOUBLE_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.FLOAT_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.FLOAT_TYPE); insertGetPrimitive(cw, classNameInternal, fields, Type.CHAR_TYPE); insertSetPrimitive(cw, classNameInternal, fields, Type.CHAR_TYPE); insertGetString(cw, classNameInternal, fields); cw.visitEnd(); accessClass = loader.defineClass(accessClassName, cw.toByteArray()); } try { FieldAccess access = (FieldAccess)accessClass.newInstance(); access.fieldNames = fieldNames; return access; } catch (Exception ex) { throw new RuntimeException("Error constructing field access class: " + accessClassName, ex); } } static private void insertConstructor (ClassWriter cw) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "com/esotericsoftware/reflectasm/FieldAccess", "", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } static private void insertSetObject (ClassWriter cw, String classNameInternal, ArrayList fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 2); if (!fields.isEmpty()) { maxStack--; Label[] labels = new Label[fields.size()]; for (int i = 0, n = labels.length; i < n; i++) labels[i] = new Label(); Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0, n = labels.length; i < n; i++) { Field field = fields.get(i); Type fieldType = Type.getType(field.getType()); mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitVarInsn(ALOAD, 3); switch (fieldType.getSort()) { case Type.BOOLEAN: mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); break; case Type.BYTE: mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B"); break; case Type.CHAR: mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); break; case Type.SHORT: mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); break; case Type.INT: mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); break; case Type.FLOAT: mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); break; case Type.LONG: mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); break; case Type.DOUBLE: mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); break; case Type.ARRAY: mv.visitTypeInsn(CHECKCAST, fieldType.getDescriptor()); break; case Type.OBJECT: mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); break; } mv.visitFieldInsn(PUTFIELD, classNameInternal, field.getName(), fieldType.getDescriptor()); mv.visitInsn(RETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } mv = insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, 4); mv.visitEnd(); } static private void insertGetObject (ClassWriter cw, String classNameInternal, ArrayList fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 2); if (!fields.isEmpty()) { maxStack--; Label[] labels = new Label[fields.size()]; for (int i = 0, n = labels.length; i < n; i++) labels[i] = new Label(); Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0, n = labels.length; i < n; i++) { Field field = fields.get(i); mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), Type.getDescriptor(field.getType())); Type fieldType = Type.getType(field.getType()); switch (fieldType.getSort()) { case Type.BOOLEAN: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); break; case Type.BYTE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); break; case Type.CHAR: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); break; case Type.SHORT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); break; case Type.INT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); break; case Type.FLOAT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); break; case Type.LONG: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); break; case Type.DOUBLE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); break; } mv.visitInsn(ARETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, 3); mv.visitEnd(); } static private void insertGetString (ClassWriter cw, String classNameInternal, ArrayList fields) { int maxStack = 6; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 2); if (!fields.isEmpty()) { maxStack--; Label[] labels = new Label[fields.size()]; Label labelForInvalidTypes = new Label(); boolean hasAnyBadTypeLabel = false; for (int i = 0, n = labels.length; i < n; i++) { if (fields.get(i).getType().equals(String.class)) labels[i] = new Label(); else { labels[i] = labelForInvalidTypes; hasAnyBadTypeLabel = true; } } Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0, n = labels.length; i < n; i++) { if (!labels[i].equals(labelForInvalidTypes)) { mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitFieldInsn(GETFIELD, classNameInternal, fields.get(i).getName(), "Ljava/lang/String;"); mv.visitInsn(ARETURN); } } // Rest of fields: different type if (hasAnyBadTypeLabel) { mv.visitLabel(labelForInvalidTypes); mv.visitFrame(F_SAME, 0, null, 0, null); insertThrowExceptionForFieldType(mv, "String"); } // Default: field not found mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, 3); mv.visitEnd(); } static private void insertSetPrimitive (ClassWriter cw, String classNameInternal, ArrayList fields, Type primitiveType) { int maxStack = 6; int maxLocals = 4; // See correction below for LLOAD and DLOAD final String setterMethodName; final String typeNameInternal = primitiveType.getDescriptor(); final int loadValueInstruction; switch (primitiveType.getSort()) { case Type.BOOLEAN: setterMethodName = "setBoolean"; loadValueInstruction = ILOAD; break; case Type.BYTE: setterMethodName = "setByte"; loadValueInstruction = ILOAD; break; case Type.CHAR: setterMethodName = "setChar"; loadValueInstruction = ILOAD; break; case Type.SHORT: setterMethodName = "setShort"; loadValueInstruction = ILOAD; break; case Type.INT: setterMethodName = "setInt"; loadValueInstruction = ILOAD; break; case Type.FLOAT: setterMethodName = "setFloat"; loadValueInstruction = FLOAD; break; case Type.LONG: setterMethodName = "setLong"; loadValueInstruction = LLOAD; maxLocals++; // (LLOAD and DLOAD actually load two slots) break; case Type.DOUBLE: setterMethodName = "setDouble"; loadValueInstruction = DLOAD; // (LLOAD and DLOAD actually load two slots) maxLocals++; break; default: setterMethodName = "set"; loadValueInstruction = ALOAD; break; } MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, setterMethodName, "(Ljava/lang/Object;I" + typeNameInternal + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 2); if (!fields.isEmpty()) { maxStack--; Label[] labels = new Label[fields.size()]; Label labelForInvalidTypes = new Label(); boolean hasAnyBadTypeLabel = false; for (int i = 0, n = labels.length; i < n; i++) { if (Type.getType(fields.get(i).getType()).equals(primitiveType)) labels[i] = new Label(); else { labels[i] = labelForInvalidTypes; hasAnyBadTypeLabel = true; } } Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0, n = labels.length; i < n; i++) { if (!labels[i].equals(labelForInvalidTypes)) { mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitVarInsn(loadValueInstruction, 3); mv.visitFieldInsn(PUTFIELD, classNameInternal, fields.get(i).getName(), typeNameInternal); mv.visitInsn(RETURN); } } // Rest of fields: different type if (hasAnyBadTypeLabel) { mv.visitLabel(labelForInvalidTypes); mv.visitFrame(F_SAME, 0, null, 0, null); insertThrowExceptionForFieldType(mv, primitiveType.getClassName()); } // Default: field not found mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } mv = insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, maxLocals); mv.visitEnd(); } static private void insertGetPrimitive (ClassWriter cw, String classNameInternal, ArrayList fields, Type primitiveType) { int maxStack = 6; final String getterMethodName; final String typeNameInternal = primitiveType.getDescriptor(); final int returnValueInstruction; switch (primitiveType.getSort()) { case Type.BOOLEAN: getterMethodName = "getBoolean"; returnValueInstruction = IRETURN; break; case Type.BYTE: getterMethodName = "getByte"; returnValueInstruction = IRETURN; break; case Type.CHAR: getterMethodName = "getChar"; returnValueInstruction = IRETURN; break; case Type.SHORT: getterMethodName = "getShort"; returnValueInstruction = IRETURN; break; case Type.INT: getterMethodName = "getInt"; returnValueInstruction = IRETURN; break; case Type.FLOAT: getterMethodName = "getFloat"; returnValueInstruction = FRETURN; break; case Type.LONG: getterMethodName = "getLong"; returnValueInstruction = LRETURN; break; case Type.DOUBLE: getterMethodName = "getDouble"; returnValueInstruction = DRETURN; break; default: getterMethodName = "get"; returnValueInstruction = ARETURN; break; } MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getterMethodName, "(Ljava/lang/Object;I)" + typeNameInternal, null, null); mv.visitCode(); mv.visitVarInsn(ILOAD, 2); if (!fields.isEmpty()) { maxStack--; Label[] labels = new Label[fields.size()]; Label labelForInvalidTypes = new Label(); boolean hasAnyBadTypeLabel = false; for (int i = 0, n = labels.length; i < n; i++) { if (Type.getType(fields.get(i).getType()).equals(primitiveType)) labels[i] = new Label(); else { labels[i] = labelForInvalidTypes; hasAnyBadTypeLabel = true; } } Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); for (int i = 0, n = labels.length; i < n; i++) { Field field = fields.get(i); if (!labels[i].equals(labelForInvalidTypes)) { mv.visitLabel(labels[i]); mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), typeNameInternal); mv.visitInsn(returnValueInstruction); } } // Rest of fields: different type if (hasAnyBadTypeLabel) { mv.visitLabel(labelForInvalidTypes); mv.visitFrame(F_SAME, 0, null, 0, null); insertThrowExceptionForFieldType(mv, primitiveType.getClassName()); } // Default: field not found mv.visitLabel(defaultLabel); mv.visitFrame(F_SAME, 0, null, 0, null); } mv = insertThrowExceptionForFieldNotFound(mv); mv.visitMaxs(maxStack, 3); mv.visitEnd(); } static private MethodVisitor insertThrowExceptionForFieldNotFound (MethodVisitor mv) { mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException"); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("Field not found: "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V"); mv.visitVarInsn(ILOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "", "(Ljava/lang/String;)V"); mv.visitInsn(ATHROW); return mv; } static private MethodVisitor insertThrowExceptionForFieldType (MethodVisitor mv, String fieldType) { mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException"); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("The field is not declared as " + fieldType + ": "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V"); mv.visitVarInsn(ILOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "", "(Ljava/lang/String;)V"); mv.visitInsn(ATHROW); return mv; } } libreflectasm-java-1.05/java/src/com/esotericsoftware/reflectasm/MethodAccess.java000066400000000000000000000223571210575633500304220ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import static org.objectweb.asm.Opcodes.*; public abstract class MethodAccess { private String[] methodNames; private Class[][] parameterTypes; abstract public Object invoke (Object object, int methodIndex, Object... args); /** Invokes the first method with the specified name. */ public Object invoke (Object object, String methodName, Object... args) { return invoke(object, getIndex(methodName), args); } /** Returns the index of the first method with the specified name. */ public int getIndex (String methodName) { for (int i = 0, n = methodNames.length; i < n; i++) if (methodNames[i].equals(methodName)) return i; throw new IllegalArgumentException("Unable to find public method: " + methodName); } public int getIndex (String methodName, Class... paramTypes) { for (int i = 0, n = methodNames.length; i < n; i++) if (methodNames[i].equals(methodName) && Arrays.equals(paramTypes, parameterTypes[i])) return i; throw new IllegalArgumentException("Unable to find public method: " + methodName + " " + Arrays.toString(parameterTypes)); } public String[] getMethodNames () { return methodNames; } public Class[][] getParameterTypes () { return parameterTypes; } static public MethodAccess get (Class type) { AccessClassLoader loader = AccessClassLoader.get(type); ArrayList methods = new ArrayList(); Class nextClass = type; while (nextClass != Object.class) { Method[] declaredMethods = nextClass.getDeclaredMethods(); for (int i = 0, n = declaredMethods.length; i < n; i++) { Method method = declaredMethods[i]; int modifiers = method.getModifiers(); if (Modifier.isStatic(modifiers)) continue; if (Modifier.isPrivate(modifiers)) continue; methods.add(method); } nextClass = nextClass.getSuperclass(); } Class[][] parameterTypes = new Class[methods.size()][]; String[] methodNames = new String[methods.size()]; for (int i = 0, n = methodNames.length; i < n; i++) { Method method = methods.get(i); methodNames[i] = method.getName(); parameterTypes[i] = method.getParameterTypes(); } String className = type.getName(); String accessClassName = className + "MethodAccess"; if (accessClassName.startsWith("java.")) accessClassName = "reflectasm." + accessClassName; Class accessClass = null; try { accessClass = loader.loadClass(accessClassName); } catch (ClassNotFoundException ignored) { } if (accessClass == null) { String accessClassNameInternal = accessClassName.replace('.', '/'); String classNameInternal = className.replace('.', '/'); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); MethodVisitor mv; cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null, "com/esotericsoftware/reflectasm/MethodAccess", null); { mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "com/esotericsoftware/reflectasm/MethodAccess", "", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "invoke", "(Ljava/lang/Object;I[Ljava/lang/Object;)Ljava/lang/Object;", null, null); mv.visitCode(); if (!methods.isEmpty()) { mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, classNameInternal); mv.visitVarInsn(ASTORE, 4); mv.visitVarInsn(ILOAD, 2); Label[] labels = new Label[methods.size()]; for (int i = 0, n = labels.length; i < n; i++) labels[i] = new Label(); Label defaultLabel = new Label(); mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); StringBuilder buffer = new StringBuilder(128); for (int i = 0, n = labels.length; i < n; i++) { mv.visitLabel(labels[i]); if (i == 0) mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {classNameInternal}, 0, null); else mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 4); buffer.setLength(0); buffer.append('('); Method method = methods.get(i); Class[] paramTypes = method.getParameterTypes(); for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { mv.visitVarInsn(ALOAD, 3); mv.visitIntInsn(BIPUSH, paramIndex); mv.visitInsn(AALOAD); Type paramType = Type.getType(paramTypes[paramIndex]); switch (paramType.getSort()) { case Type.BOOLEAN: mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); break; case Type.BYTE: mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B"); break; case Type.CHAR: mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); break; case Type.SHORT: mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); break; case Type.INT: mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); break; case Type.FLOAT: mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); break; case Type.LONG: mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); break; case Type.DOUBLE: mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); break; case Type.ARRAY: mv.visitTypeInsn(CHECKCAST, paramType.getDescriptor()); break; case Type.OBJECT: mv.visitTypeInsn(CHECKCAST, paramType.getInternalName()); break; } buffer.append(paramType.getDescriptor()); } buffer.append(')'); buffer.append(Type.getDescriptor(method.getReturnType())); mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, method.getName(), buffer.toString()); switch (Type.getType(method.getReturnType()).getSort()) { case Type.VOID: mv.visitInsn(ACONST_NULL); break; case Type.BOOLEAN: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); break; case Type.BYTE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); break; case Type.CHAR: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); break; case Type.SHORT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); break; case Type.INT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); break; case Type.FLOAT: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); break; case Type.LONG: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); break; case Type.DOUBLE: mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); break; } mv.visitInsn(ARETURN); } mv.visitLabel(defaultLabel); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException"); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("Method not found: "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V"); mv.visitVarInsn(ILOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "", "(Ljava/lang/String;)V"); mv.visitInsn(ATHROW); mv.visitMaxs(0, 0); mv.visitEnd(); } cw.visitEnd(); byte[] data = cw.toByteArray(); accessClass = loader.defineClass(accessClassName, data); } try { MethodAccess access = (MethodAccess)accessClass.newInstance(); access.methodNames = methodNames; access.parameterTypes = parameterTypes; return access; } catch (Exception ex) { throw new RuntimeException("Error constructing method access class: " + accessClassName, ex); } } } libreflectasm-java-1.05/java/test/000077500000000000000000000000001210575633500171015ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/000077500000000000000000000000001210575633500176575ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/000077500000000000000000000000001210575633500232475ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/000077500000000000000000000000001210575633500253745ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/ClassLoaderTest.java000066400000000000000000000041661210575633500313020ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import junit.framework.TestCase; public class ClassLoaderTest extends TestCase { public void testDifferentClassloaders () throws Exception { // This classloader can see only the Test class and core Java classes. ClassLoader testClassLoader = new ClassLoader() { protected synchronized Class loadClass (String name, boolean resolve) throws ClassNotFoundException { Class c = findLoadedClass(name); if (c != null) return c; if (name.startsWith("java.")) return super.loadClass(name, resolve); if (!name.equals("com.esotericsoftware.reflectasm.ClassLoaderTest$Test")) throw new ClassNotFoundException("Class not found on purpose: " + name); ByteArrayOutputStream output = new ByteArrayOutputStream(32 * 1024); InputStream input = ClassLoaderTest.class.getResourceAsStream("/" + name.replace('.', '/') + ".class"); if (input == null) return null; try { byte[] buffer = new byte[4096]; int total = 0; while (true) { int length = input.read(buffer, 0, buffer.length); if (length == -1) break; output.write(buffer, 0, length); } } catch (IOException ex) { throw new ClassNotFoundException("Error reading class file.", ex); } finally { try { input.close(); } catch (IOException ignored) { } } byte[] buffer = output.toByteArray(); return defineClass(name, buffer, 0, buffer.length); } }; Class testClass = testClassLoader.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test"); Object testObject = testClass.newInstance(); // Ensure AccessClassLoader can access both the Test class and FieldAccess. FieldAccess access = FieldAccess.get(testObject.getClass()); access.set(testObject, "name", "first"); assertEquals("first", testObject.toString()); assertEquals("first", access.get(testObject, "name")); } static public class Test { public String name; public String toString () { return name; } } } libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/ConstructorAccessTest.java000066400000000000000000000025011210575633500325440ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import junit.framework.TestCase; public class ConstructorAccessTest extends TestCase { public void testNewInstance () { ConstructorAccess access = ConstructorAccess.get(SomeClass.class); SomeClass someObject = new SomeClass(); assertEquals(someObject, access.newInstance()); assertEquals(someObject, access.newInstance()); assertEquals(someObject, access.newInstance()); } static public class SomeClass { public String name; public int intValue; protected float test1; Float test2; private String test3; public boolean equals (Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; SomeClass other = (SomeClass)obj; if (intValue != other.intValue) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (Float.floatToIntBits(test1) != Float.floatToIntBits(other.test1)) return false; if (test2 == null) { if (other.test2 != null) return false; } else if (!test2.equals(other.test2)) return false; if (test3 == null) { if (other.test3 != null) return false; } else if (!test3.equals(other.test3)) return false; return true; } } } libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/FieldAccessTest.java000066400000000000000000000076501210575633500312540ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import junit.framework.TestCase; public class FieldAccessTest extends TestCase { public void testNameSetAndGet () { FieldAccess access = FieldAccess.get(SomeClass.class); SomeClass test = new SomeClass(); assertEquals(null, test.name); access.set(test, "name", "first"); assertEquals("first", test.name); assertEquals("first", access.get(test, "name")); assertEquals(0, test.intValue); access.set(test, "intValue", 1234); assertEquals(1234, test.intValue); assertEquals(1234, access.get(test, "intValue")); } public void testIndexSetAndGet () { FieldAccess access = FieldAccess.get(SomeClass.class); SomeClass test = new SomeClass(); int index; assertEquals(null, test.name); index = access.getIndex("name"); access.set(test, index, "first"); assertEquals("first", test.name); assertEquals("first", access.get(test, index)); index = access.getIndex("intValue"); assertEquals(0, test.intValue); access.set(test, index, 1234); assertEquals(1234, test.intValue); assertEquals(1234, access.get(test, index)); assertEquals(false, access.getBoolean(test, access.getIndex("booleanField"))); access.setBoolean(test, access.getIndex("booleanField"), true); assertEquals(true, access.getBoolean(test, access.getIndex("booleanField"))); assertEquals(0, access.getByte(test, access.getIndex("byteField"))); access.setByte(test, access.getIndex("byteField"), (byte)23); assertEquals(23, access.getByte(test, access.getIndex("byteField"))); assertEquals(0, access.getChar(test, access.getIndex("charField"))); access.setChar(test, access.getIndex("charField"), (char)53); assertEquals(53, access.getChar(test, access.getIndex("charField"))); assertEquals(0, access.getShort(test, access.getIndex("shortField"))); access.setShort(test, access.getIndex("shortField"), (short)123); assertEquals(123, access.getShort(test, access.getIndex("shortField"))); assertEquals(0, access.getInt(test, access.getIndex("intField"))); access.setInt(test, access.getIndex("intField"), 123); assertEquals(123, access.getInt(test, access.getIndex("intField"))); assertEquals(0, access.getLong(test, access.getIndex("longField"))); access.setLong(test, access.getIndex("longField"), 123456789l); assertEquals(123456789l, access.getLong(test, access.getIndex("longField"))); assertEquals(0f, access.getFloat(test, access.getIndex("floatField"))); access.setFloat(test, access.getIndex("floatField"), 1.23f); assertEquals(1.23f, access.getFloat(test, access.getIndex("floatField"))); assertEquals(0d, access.getDouble(test, access.getIndex("doubleField"))); access.setDouble(test, access.getIndex("doubleField"), 123.456); assertEquals(123.456, access.getDouble(test, access.getIndex("doubleField"))); } public void testEmptyClass () { FieldAccess access = FieldAccess.get(EmptyClass.class); try { access.getIndex("name"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.get(new EmptyClass(), "meow"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.get(new EmptyClass(), 0); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.set(new EmptyClass(), "foo", "moo"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } } static public class SomeClass { public String name; public int intValue; protected float test1; Float test2; private String test3; public boolean booleanField; public byte byteField; public char charField; public short shortField; public int intField; public long longField; public float floatField; public double doubleField; } static public class EmptyClass { } } libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/MethodAccessTest.java000066400000000000000000000053661210575633500314530ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm; import com.esotericsoftware.reflectasm.FieldAccessTest.EmptyClass; import junit.framework.TestCase; public class MethodAccessTest extends TestCase { public void testInvoke () { MethodAccess access = MethodAccess.get(SomeClass.class); SomeClass someObject = new SomeClass(); Object value; value = access.invoke(someObject, "getName"); assertEquals(null, value); value = access.invoke(someObject, "setName", "sweet"); assertEquals(null, value); value = access.invoke(someObject, "getName"); assertEquals("sweet", value); value = access.invoke(someObject, "setName", (Object)null); assertEquals(null, value); value = access.invoke(someObject, "getName"); assertEquals(null, value); value = access.invoke(someObject, "getIntValue"); assertEquals(0, value); value = access.invoke(someObject, "setIntValue", 1234); assertEquals(null, value); value = access.invoke(someObject, "getIntValue"); assertEquals(1234, value); value = access.invoke(someObject, "methodWithManyArguments", 1, 2f, 3, 4.2f, null, null, null); assertEquals("test", value); int index = access.getIndex("methodWithManyArguments", int.class, float.class, Integer.class, Float.class, SomeClass.class, SomeClass.class, SomeClass.class); assertEquals(access.getIndex("methodWithManyArguments"), index); } public void testEmptyClass () { MethodAccess access = MethodAccess.get(EmptyClass.class); try { access.getIndex("name"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.getIndex("name", String.class); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.invoke(new EmptyClass(), "meow", "moo"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.invoke(new EmptyClass(), 0); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } try { access.invoke(new EmptyClass(), 0, "moo"); fail(); } catch (IllegalArgumentException expected) { // expected.printStackTrace(); } } static public class EmptyClass { } static public class SomeClass { private String name; private int intValue; public String getName () { return name; } public void setName (String name) { this.name = name; } public int getIntValue () { return intValue; } public void setIntValue (int intValue) { this.intValue = intValue; } public String methodWithManyArguments (int i, float f, Integer I, Float F, SomeClass c, SomeClass c1, SomeClass c2) { return "test"; } } } libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/benchmark/000077500000000000000000000000001210575633500273265ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/benchmark/Benchmark.java000066400000000000000000000036761210575633500320770ustar00rootroot00000000000000 package com.esotericsoftware.reflectasm.benchmark; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map.Entry; public class Benchmark { public boolean warmup = true; public HashMap testTimes = new HashMap(); private long s; public void start () { s = System.nanoTime(); } public void end (String name) { if (warmup) return; long e = System.nanoTime(); long time = e - s; Long oldTime = testTimes.get(name); if (oldTime == null || time < oldTime) testTimes.put(name, time); System.out.println(name + ": " + time / 1000000f + " ms"); } public void chart (String title) { Comparator comparator = new Comparator() { public int compare (Entry o1, Entry o2) { // return ((String)o1.getKey()).compareTo((String)o2.getKey()); return (int)((Long)o1.getValue() - (Long)o2.getValue()); } }; ArrayList list = new ArrayList(testTimes.entrySet()); Collections.sort(list, comparator); StringBuilder names = new StringBuilder(512); StringBuilder times = new StringBuilder(512); long max = 0; int count = 0; for (Entry entry : list) { String name = entry.getKey(); names.insert(0, '|'); names.insert(0, name); long time = entry.getValue(); times.append(time); times.append(','); max = Math.max(max, time); count++; } times.setLength(times.length() - 1); names.setLength(names.length() - 1); int height = count * 18 + 21; int width = Math.min(700, 300000 / height); System.out.println("[img]http://chart.apis.google.com/chart?chtt=" + title + "&" + "chs=" + width + "x" + height + "&chd=t:" + times + "&chds=0," + max + "&chxl=0:|" + names + "&cht=bhg&chbh=10&chxt=y&" + "chco=660000|660033|660066|660099|6600CC|6600FF|663300|663333|" + "663366|663399|6633CC|6633FF|666600|666633|666666[/img]\n"); } } ConstructorAccessBenchmark.java000066400000000000000000000023051210575633500353740ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/benchmark package com.esotericsoftware.reflectasm.benchmark; import com.esotericsoftware.reflectasm.ConstructorAccess; public class ConstructorAccessBenchmark extends Benchmark { public ConstructorAccessBenchmark () throws Exception { int count = 1000000; Object[] dontCompileMeAway = new Object[count]; Class type = SomeClass.class; ConstructorAccess access = ConstructorAccess.get(type); for (int i = 0; i < 100; i++) for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = access.newInstance(); for (int i = 0; i < 100; i++) for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = type.newInstance(); warmup = false; for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = access.newInstance(); end("ConstructorAccess"); } for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = type.newInstance(); end("Reflection"); } chart("Constructor"); } static public class SomeClass { public String name; } public static void main (String[] args) throws Exception { new ConstructorAccessBenchmark(); } } FieldAccessBenchmark.java000066400000000000000000000030041210575633500340670ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/benchmark package com.esotericsoftware.reflectasm.benchmark; import java.lang.reflect.Field; import java.util.HashMap; import com.esotericsoftware.reflectasm.FieldAccess; public class FieldAccessBenchmark extends Benchmark { public FieldAccessBenchmark () throws Exception { int count = 1000000; Object[] dontCompileMeAway = new Object[count]; FieldAccess access = FieldAccess.get(SomeClass.class); SomeClass someObject = new SomeClass(); int index = access.getIndex("name"); Field field = SomeClass.class.getField("name"); for (int i = 0; i < 100; i++) { for (int ii = 0; ii < count; ii++) { access.set(someObject, index, "first"); dontCompileMeAway[ii] = access.get(someObject, index); } for (int ii = 0; ii < count; ii++) { field.set(someObject, "first"); dontCompileMeAway[ii] = field.get(someObject); } } warmup = false; for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) { access.set(someObject, index, "first"); dontCompileMeAway[ii] = access.get(someObject, index); } end("FieldAccess"); } for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) { field.set(someObject, "first"); dontCompileMeAway[ii] = field.get(someObject); } end("Reflection"); } chart("Field Set/Get"); } static public class SomeClass { public String name; } public static void main (String[] args) throws Exception { new FieldAccessBenchmark(); } } MethodAccessBenchmark.java000066400000000000000000000026411210575633500342720ustar00rootroot00000000000000libreflectasm-java-1.05/java/test/com/esotericsoftware/reflectasm/benchmark package com.esotericsoftware.reflectasm.benchmark; import java.lang.reflect.Method; import java.util.HashMap; import com.esotericsoftware.reflectasm.MethodAccess; public class MethodAccessBenchmark extends Benchmark { public MethodAccessBenchmark () throws Exception { int count = 100000; Object[] dontCompileMeAway = new Object[count]; MethodAccess access = MethodAccess.get(SomeClass.class); SomeClass someObject = new SomeClass(); int index = access.getIndex("getName"); Method method = SomeClass.class.getMethod("getName"); for (int i = 0; i < 100; i++) { for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = access.invoke(someObject, index); for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = method.invoke(someObject); } warmup = false; for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = access.invoke(someObject, index); end("MethodAccess"); } for (int i = 0; i < 100; i++) { start(); for (int ii = 0; ii < count; ii++) dontCompileMeAway[ii] = method.invoke(someObject); end("Reflection"); } chart("Method Call"); } static public class SomeClass { private String name = "something"; public String getName () { return name; } } public static void main (String[] args) throws Exception { new MethodAccessBenchmark(); } }