Author: mbenson Date: Mon Sep 9 22:27:27 2013 New Revision: 1521303 URL: http://svn.apache.org/r1521303 Log: use asm commons to drastically shrink code; eliminate Unsafe class that relies on Sun/Oracle private APIs; incidentally fix a bug where caught exceptions had to match declared type exactly, with no notion of inheritance, to be correctly rethrown
Modified: commons/proper/proxy/branches/version-2.0-work/asm4/pom.xml commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java commons/proper/proxy/branches/version-2.0-work/pom.xml Modified: commons/proper/proxy/branches/version-2.0-work/asm4/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/asm4/pom.xml?rev=1521303&r1=1521302&r2=1521303&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/asm4/pom.xml (original) +++ commons/proper/proxy/branches/version-2.0-work/asm4/pom.xml Mon Sep 9 22:27:27 2013 @@ -35,8 +35,12 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>org.apache.xbean</groupId> - <artifactId>xbean-asm4-shaded</artifactId> + <groupId>org.ow2.asm</groupId> + <artifactId>asm</artifactId> + </dependency> + <dependency> + <groupId>org.ow2.asm</groupId> + <artifactId>asm-commons</artifactId> </dependency> <dependency> <groupId>${project.groupId}</groupId> Modified: commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java?rev=1521303&r1=1521302&r2=1521303&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java (original) +++ commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java Mon Sep 9 22:27:27 2013 @@ -16,6 +16,14 @@ */ package org.apache.commons.proxy2.asm4; +import java.io.Serializable; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.concurrent.atomic.AtomicInteger; + import org.apache.commons.proxy2.Interceptor; import org.apache.commons.proxy2.Invocation; import org.apache.commons.proxy2.Invoker; @@ -25,22 +33,11 @@ import org.apache.commons.proxy2.excepti import org.apache.commons.proxy2.impl.AbstractProxyClassGenerator; import org.apache.commons.proxy2.impl.AbstractSubclassingProxyFactory; import org.apache.commons.proxy2.impl.ProxyClassCache; -import org.apache.xbean.asm4.ClassWriter; -import org.apache.xbean.asm4.Label; -import org.apache.xbean.asm4.MethodVisitor; -import org.apache.xbean.asm4.Opcodes; -import org.apache.xbean.asm4.Type; - -import java.io.Serializable; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; -import java.util.concurrent.atomic.AtomicInteger; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.GeneratorAdapter; public class ASM4ProxyFactory extends AbstractSubclassingProxyFactory { @@ -64,14 +61,20 @@ public class ASM4ProxyFactory extends Ab return createProxy(classLoader, new InvokerInvocationHandler(invoker), proxyClasses); } - private <T> T createProxy(final ClassLoader classLoader, InvocationHandler invocationHandler, final Class<?>... proxyClasses) + private <T> T createProxy(final ClassLoader classLoader, final InvocationHandler invocationHandler, final Class<?>... proxyClasses) { - final Class<?> proxyClass = PROXY_CLASS_CACHE.getProxyClass(classLoader, proxyClasses); - final Object instance = Unsafe.allocateInstance(proxyClass); - Unsafe.setValue(ProxyGenerator.getDeclaredField(proxyClass, ProxyGenerator.HANDLER_NAME), instance, invocationHandler); - @SuppressWarnings("unchecked") - final T result = (T) instance; - return result; + final Class<?> proxyClass = PROXY_CLASS_CACHE.getProxyClass( + classLoader, proxyClasses); + try + { + @SuppressWarnings("unchecked") + final T result = (T) proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler); + return result; + } + catch (Exception e) + { + throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e); + } } private static class ProxyGenerator extends AbstractProxyClassGenerator implements Opcodes @@ -79,6 +82,7 @@ public class ASM4ProxyFactory extends Ab private static final AtomicInteger CLASS_NUMBER = new AtomicInteger(0); private static final String CLASSNAME_PREFIX = "CommonsProxyASM4_"; private static final String HANDLER_NAME = "__handler"; + private static final Type HANDLER_TYPE = Type.getType(InvocationHandler.class); @Override public Class<?> generateProxyClass(final ClassLoader classLoader, final Class<?>... proxyClasses) @@ -92,7 +96,7 @@ public class ASM4ProxyFactory extends Ab try { final byte[] proxyBytes = generateProxy(superclass, classFileName, implementationMethods, interfaces); - return Unsafe.defineClass(classLoader, superclass, proxyName, proxyBytes); + return loadClass(classLoader, proxyName, proxyBytes); } catch (final Exception e) { @@ -100,51 +104,55 @@ public class ASM4ProxyFactory extends Ab } } - private static Field getDeclaredField(final Class<?> clazz, final String fieldName) - { - try - { - return clazz.getDeclaredField(fieldName); - } - catch (NoSuchFieldException e) - { - final String message = String.format("Proxy class does not contain expected field \"%s\": %s", fieldName, clazz.getName()); - throw new IllegalStateException(message, e); - } - } - private static byte[] generateProxy(final Class<?> classToProxy, final String proxyName, final Method[] methods, final Class<?>... interfaces) throws ProxyFactoryException { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - final String proxyClassFileName = proxyName.replace('.', '/'); - final String classFileName = classToProxy.getName().replace('.', '/'); + final Type proxyType = Type.getObjectType(proxyName); // push class signature final String[] interfaceNames = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { - final Class<?> anInterface = interfaces[i]; - interfaceNames[i] = anInterface.getName().replace('.', '/'); + interfaceNames[i] = Type.getType(interfaces[i]).getInternalName(); } - cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, proxyClassFileName, null, classFileName, interfaceNames); + final Type superType = Type.getType(classToProxy); + cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, proxyType.getInternalName(), null, superType.getInternalName(), interfaceNames); // push InvocationHandler fields - cw.visitField(ACC_FINAL + ACC_PRIVATE, HANDLER_NAME, "Ljava/lang/reflect/InvocationHandler;", null, null).visitEnd(); + cw.visitField(ACC_FINAL + ACC_PRIVATE, HANDLER_NAME, HANDLER_TYPE.getDescriptor(), null, null).visitEnd(); + + init(cw, proxyType, superType); for (final Method method : methods) { - processMethod(cw, method, proxyClassFileName, HANDLER_NAME); + processMethod(cw, method, proxyType, HANDLER_NAME); } return cw.toByteArray(); } - private static void processMethod(final ClassWriter cw, final Method method, final String proxyName, final String handlerName) throws ProxyFactoryException { - final Class<?> returnType = method.getReturnType(); - final Class<?>[] parameterTypes = method.getParameterTypes(); - final Class<?>[] exceptionTypes = method.getExceptionTypes(); + private static void init(final ClassWriter cw, final Type proxyType, Type superType) + { + final GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, new org.objectweb.asm.commons.Method("<init>", + Type.VOID_TYPE, new Type[] { HANDLER_TYPE }), null, null, cw); + // invoke super constructor: + mg.loadThis(); + mg.invokeConstructor(superType, org.objectweb.asm.commons.Method.getMethod("void <init> ()")); + + // assign handler: + mg.loadThis(); + mg.loadArg(0); + mg.putField(proxyType, HANDLER_NAME, HANDLER_TYPE); + mg.returnValue(); + mg.endMethod(); + } + + private static void processMethod(final ClassWriter cw, final Method method, final Type proxyType, final String handlerName) throws ProxyFactoryException { + final Type sig = Type.getType(method); + final Type[] exceptionTypes = getTypes(method.getExceptionTypes()); + final int modifiers = method.getModifiers(); // push the method definition @@ -158,502 +166,170 @@ public class ASM4ProxyFactory extends Ab modifier = ACC_PROTECTED; } - final MethodVisitor mv = cw.visitMethod(modifier, method.getName(), getMethodSignatureAsString(returnType, parameterTypes), null, null); - mv.visitCode(); + final org.objectweb.asm.commons.Method m = org.objectweb.asm.commons.Method.getMethod(method); + final GeneratorAdapter mg = new GeneratorAdapter(modifier, m, null, getTypes(method.getExceptionTypes()), cw); - // push try/catch block, to catch declared exceptions, and to catch java.lang.Throwable - final Label l0 = new Label(); - final Label l1 = new Label(); - final Label l2 = new Label(); + final Label tryBlock = exceptionTypes.length > 0 ? mg.mark() : null; - if (exceptionTypes.length > 0) - { - mv.visitTryCatchBlock(l0, l1, l2, "java/lang/reflect/InvocationTargetException"); - } - - // push try code - mv.visitLabel(l0); - final String classNameToOverride = method.getDeclaringClass().getName().replace('.', '/'); - mv.visitLdcInsn(Type.getType("L" + classNameToOverride + ";")); + mg.push(Type.getType(method.getDeclaringClass())); // the following code generates the bytecode for this line of Java: // Method method = <proxy>.class.getMethod("add", new Class[] { <array of function argument classes> }); // get the method name to invoke, and push to stack - mv.visitLdcInsn(method.getName()); - // create the Class[] - createArrayDefinition(mv, parameterTypes.length, Class.class); + mg.push(method.getName()); - int length = 1; + // create the Class[] + mg.push(sig.getArgumentTypes().length); + final Type classType = Type.getType(Class.class); + mg.newArray(classType); // push parameters into array - for (int i = 0; i < parameterTypes.length; i++) + for (int i = 0; i < sig.getArgumentTypes().length; i++) { // keep copy of array on stack - mv.visitInsn(DUP); - - final Class<?> parameterType = parameterTypes[i]; - - // push number onto stack - pushIntOntoStack(mv, i); - - if (parameterType.isPrimitive()) - { - final String wrapperType = getWrapperType(parameterType); - mv.visitFieldInsn(GETSTATIC, wrapperType, "TYPE", "Ljava/lang/Class;"); - } else { - mv.visitLdcInsn(Type.getType(getAsmTypeAsString(parameterType, true))); - } - - mv.visitInsn(AASTORE); + mg.dup(); - if (Long.TYPE.equals(parameterType) || Double.TYPE.equals(parameterType)) - { - length += 2; - } else { - length++; - } + // push index onto stack + mg.push(i); + mg.push(sig.getArgumentTypes()[i]); + mg.arrayStore(classType); } // invoke getMethod() with the method name and the array of types - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"); - + mg.invokeVirtual(classType, org.objectweb.asm.commons.Method.getMethod("java.lang.reflect.Method getDeclaredMethod(String, Class[])")); // store the returned method for later - mv.visitVarInsn(ASTORE, length); // the following code generates bytecode equivalent to: // return ((<returntype>) invocationHandler.invoke(this, method, new Object[] { <function arguments }))[.<primitive>Value()]; - final Label l4 = new Label(); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 0); + mg.loadThis(); - // get the invocationHandler field from this class - mv.visitFieldInsn(GETFIELD, proxyName, handlerName, "Ljava/lang/reflect/InvocationHandler;"); + mg.getField(proxyType, handlerName, HANDLER_TYPE); + // put below method: + mg.swap(); // we want to pass "this" in as the first parameter - mv.visitVarInsn(ALOAD, 0); - - // and the method we fetched earlier - mv.visitVarInsn(ALOAD, length); + mg.loadThis(); + // put below method: + mg.swap(); // need to construct the array of objects passed in // create the Object[] - createArrayDefinition(mv, parameterTypes.length, Object.class); + mg.push(sig.getArgumentTypes().length); + final Type objectType = Type.getType(Object.class); + mg.newArray(objectType); - int index = 1; // push parameters into array - for (int i = 0; i < parameterTypes.length; i++) + for (int i = 0; i < sig.getArgumentTypes().length; i++) { // keep copy of array on stack - mv.visitInsn(DUP); + mg.dup(); - final Class<?> parameterType = parameterTypes[i]; - - // push number onto stack - pushIntOntoStack(mv, i); - - if (parameterType.isPrimitive()) - { - final String wrapperType = getWrapperType(parameterType); - mv.visitVarInsn(getVarInsn(parameterType), index); + // push index onto stack + mg.push(i); - mv.visitMethodInsn(INVOKESTATIC, wrapperType, "valueOf", "(" + getPrimitiveLetter(parameterType) + ")L" + wrapperType + ";"); - mv.visitInsn(AASTORE); - - if (Long.TYPE.equals(parameterType) || Double.TYPE.equals(parameterType)) - { - index += 2; - } - else - { - index++; - } - } - else - { - mv.visitVarInsn(ALOAD, index); - mv.visitInsn(AASTORE); - index++; - } + mg.loadArg(i); + mg.valueOf(sig.getArgumentTypes()[i]); + mg.arrayStore(objectType); } // invoke the invocationHandler - mv.visitMethodInsn(INVOKEINTERFACE, "java/lang/reflect/InvocationHandler", "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"); + mg.invokeInterface(HANDLER_TYPE, org.objectweb.asm.commons.Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])")); // cast the result - mv.visitTypeInsn(CHECKCAST, getCastType(returnType)); - - if (returnType.isPrimitive() && (!Void.TYPE.equals(returnType))) - { - // get the primitive value - mv.visitMethodInsn(INVOKEVIRTUAL, getWrapperType(returnType), getPrimitiveMethod(returnType), "()" + getPrimitiveLetter(returnType)); - } + mg.unbox(sig.getReturnType()); // push return - mv.visitLabel(l1); - if (!Void.TYPE.equals(returnType)) - { - mv.visitInsn(getReturnInsn(returnType)); - } - else - { - mv.visitInsn(POP); - mv.visitInsn(RETURN); - } + mg.returnValue(); // catch InvocationTargetException if (exceptionTypes.length > 0) { - mv.visitLabel(l2); - mv.visitVarInsn(ASTORE, length); + final Type caughtExceptionType = Type.getType(InvocationTargetException.class); + mg.catchException(tryBlock, mg.mark(), caughtExceptionType); - final Label l5 = new Label(); - mv.visitLabel(l5); + final Label throwCause = new Label(); + mg.invokeVirtual(caughtExceptionType, org.objectweb.asm.commons.Method.getMethod("Throwable getCause()")); + for (int i = 0; i < exceptionTypes.length; i++) { - final Class<?> exceptionType = exceptionTypes[i]; + mg.dup(); + mg.push(exceptionTypes[i]); + mg.swap(); + mg.invokeVirtual(classType, org.objectweb.asm.commons.Method.getMethod("boolean isInstance(Object)")); + // if true, throw cause: + mg.ifZCmp(GeneratorAdapter.NE, throwCause); + } + // no exception types matched; throw UndeclaredThrowableException: + final int cause = mg.newLocal(Type.getType(Exception.class)); + mg.storeLocal(cause); + final Type undeclaredType = Type.getType(UndeclaredThrowableException.class); + mg.newInstance(undeclaredType); + mg.dup(); + mg.loadLocal(cause); + mg.invokeConstructor(undeclaredType, new org.objectweb.asm.commons.Method("<init>", Type.VOID_TYPE, + new Type[] { Type.getType(Throwable.class) })); + mg.throwException(); - mv.visitLdcInsn(Type.getType("L" + exceptionType.getName().replace('.', '/') + ";")); - mv.visitVarInsn(ALOAD, length); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "getCause", "()Ljava/lang/Throwable;"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z"); - - final Label l6 = new Label(); - mv.visitJumpInsn(IFEQ, l6); - - final Label l7 = new Label(); - mv.visitLabel(l7); - - mv.visitVarInsn(ALOAD, length); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/InvocationTargetException", "getCause", "()Ljava/lang/Throwable;"); - mv.visitTypeInsn(CHECKCAST, exceptionType.getName().replace('.', '/')); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - - if (i == (exceptionTypes.length - 1)) - { - mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException"); - mv.visitInsn(DUP); - mv.visitVarInsn(ALOAD, length); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>", "(Ljava/lang/Throwable;)V"); - mv.visitInsn(ATHROW); - } - } + mg.mark(throwCause); + mg.throwException(); } // finish this method - mv.visitMaxs(0, 0); - mv.visitEnd(); + mg.endMethod(); } - private static int getReturnInsn(final Class<?> type) + private static Type[] getTypes(Class<?>... src) { - if (type.isPrimitive()) + final Type[] result = new Type[src.length]; + for (int i = 0; i < result.length; i++) { - if (Integer.TYPE.equals(type)) - { - return IRETURN; - } - if (Boolean.TYPE.equals(type)) - { - return IRETURN; - } - if (Character.TYPE.equals(type)) - { - return IRETURN; - } - if (Byte.TYPE.equals(type)) - { - return IRETURN; - } - if (Short.TYPE.equals(type)) - { - return IRETURN; - } - if (Float.TYPE.equals(type)) - { - return FRETURN; - } - if (Long.TYPE.equals(type)) - { - return LRETURN; - } - if (Double.TYPE.equals(type)) - { - return DRETURN; - } - } - - return ARETURN; - } - - private static int getVarInsn(final Class<?> type) - { - if (type.isPrimitive()) - { - if (Integer.TYPE.equals(type)) - { - return ILOAD; - } - if (Boolean.TYPE.equals(type)) - { - return ILOAD; - } - if (Character.TYPE.equals(type)) - { - return ILOAD; - } - if (Byte.TYPE.equals(type)) - { - return ILOAD; - } - if (Short.TYPE.equals(type)) - { - return ILOAD; - } - if (Float.TYPE.equals(type)) - { - return FLOAD; - } - if (Long.TYPE.equals(type)) - { - return LLOAD; - } - if (Double.TYPE.equals(type)) - { - return DLOAD; - } + result[i] = Type.getType(src[i]); } - - throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type"); - } - - private static String getPrimitiveMethod(final Class<?> type) - { - if (Integer.TYPE.equals(type)) - { - return "intValue"; - } - if (Boolean.TYPE.equals(type)) - { - return "booleanValue"; - } - if (Character.TYPE.equals(type)) - { - return "charValue"; - } - if (Byte.TYPE.equals(type)) - { - return "byteValue"; - } - if (Short.TYPE.equals(type)) - { - return "shortValue"; - } - if (Float.TYPE.equals(type)) - { - return "floatValue"; - } - if (Long.TYPE.equals(type)) - { - return "longValue"; - } - if (Double.TYPE.equals(type)) - { - return "doubleValue"; - } - - throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type"); - } - - private static String getCastType(final Class<?> returnType) - { - if (returnType.isPrimitive()) - { - return getWrapperType(returnType); - } - return getAsmTypeAsString(returnType, false); - } - - private static String getWrapperType(final Class<?> type) - { - if (Integer.TYPE.equals(type)) - { - return Integer.class.getCanonicalName().replace('.', '/'); - } - if (Boolean.TYPE.equals(type)) - { - return Boolean.class.getCanonicalName().replace('.', '/'); - } - if (Character.TYPE.equals(type)) - { - return Character.class.getCanonicalName().replace('.', '/'); - } - if (Byte.TYPE.equals(type)) - { - return Byte.class.getCanonicalName().replace('.', '/'); - } - if (Short.TYPE.equals(type)) - { - return Short.class.getCanonicalName().replace('.', '/'); - } - if (Float.TYPE.equals(type)) - { - return Float.class.getCanonicalName().replace('.', '/'); - } - if (Long.TYPE.equals(type)) - { - return Long.class.getCanonicalName().replace('.', '/'); - } - if (Double.TYPE.equals(type)) - { - return Double.class.getCanonicalName().replace('.', '/'); - } - if (Void.TYPE.equals(type)) - { - return Void.class.getCanonicalName().replace('.', '/'); - } - - throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type"); - } - - private static void pushIntOntoStack(final MethodVisitor mv, final int i) - { - if (i == 0) - { - mv.visitInsn(ICONST_0); - } - else if (i == 1) - { - mv.visitInsn(ICONST_1); - } - else if (i == 2) - { - mv.visitInsn(ICONST_2); - } - else if (i == 3) - { - mv.visitInsn(ICONST_3); - } - else if (i == 4) - { - mv.visitInsn(ICONST_4); - } - else if (i == 5) - { - mv.visitInsn(ICONST_5); - } - else if (i > 5 && i <= 255) - { - mv.visitIntInsn(BIPUSH, i); - } - else - { - mv.visitIntInsn(SIPUSH, i); - } - } - - private static void createArrayDefinition(final MethodVisitor mv, final int size, final Class<?> type) throws ProxyFactoryException - { - // create a new array of java.lang.class (2) - if (size < 0) - { - throw new ProxyFactoryException("Array size cannot be less than zero"); - } - - pushIntOntoStack(mv, size); - mv.visitTypeInsn(ANEWARRAY, type.getCanonicalName().replace('.', '/')); - } - - private static String getMethodSignatureAsString(final Class<?> returnType, final Class<?>[] parameterTypes) - { - final StringBuilder builder = new StringBuilder("("); - for (final Class<?> parameterType : parameterTypes) { - builder.append(getAsmTypeAsString(parameterType, true)); - } - - builder.append(")"); - builder.append(getAsmTypeAsString(returnType, true)); - - return builder.toString(); + return result; } /** - * Returns the single letter that matches the given primitive in bytecode instructions + * Adapted from http://asm.ow2.org/doc/faq.html#Q5 + * + * @param b + * @return Class<?> */ - private static String getPrimitiveLetter(final Class<?> type) + private static Class<?> loadClass(final ClassLoader loader, String className, byte[] b) { - if (Integer.TYPE.equals(type)) - { - return "I"; - } - if (Void.TYPE.equals(type)) - { - return "V"; - } - if (Boolean.TYPE.equals(type)) - { - return "Z"; - } - if (Character.TYPE.equals(type)) - { - return "C"; - } - if (Byte.TYPE.equals(type)) - { - return "B"; - } - if (Short.TYPE.equals(type)) + // override classDefine (as it is protected) and define the class. + try { - return "S"; - } - if (Float.TYPE.equals(type)) - { - return "F"; - } - if (Long.TYPE.equals(type)) - { - return "J"; - } - if (Double.TYPE.equals(type)) - { - return "D"; - } - - throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type"); - } + final Method method = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, + int.class, int.class); - private static String getAsmTypeAsString(final Class<?> parameterType, final boolean wrap) - { - if (parameterType.isArray()) - { - if (parameterType.getComponentType().isPrimitive()) + // protected method invocation + final boolean accessible = method.isAccessible(); + if (!accessible) { - final Class<?> componentType = parameterType.getComponentType(); - return "[" + getPrimitiveLetter(componentType); + method.setAccessible(true); + } + try + { + return (Class<?>) method + .invoke(loader, className, b, Integer.valueOf(0), Integer.valueOf(b.length)); + } + finally + { + if (!accessible) + { + method.setAccessible(false); + } } - return "[" + getAsmTypeAsString(parameterType.getComponentType(), true); - } - if (parameterType.isPrimitive()) { - return getPrimitiveLetter(parameterType); - } - String className = parameterType.getCanonicalName(); - - if (parameterType.isMemberClass()) { - final int lastDot = className.lastIndexOf("."); - className = className.substring(0, lastDot) + "$" + className.substring(lastDot + 1); } - - if (wrap) + catch (Exception e) { - return "L" + className.replace('.', '/') + ";"; + throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e); } - return className.replace('.', '/'); } } @@ -793,177 +469,4 @@ public class ASM4ProxyFactory extends Ab } } } - - static class Unsafe - { - // sun.misc.Unsafe - private static final Object unsafe; - private static final Method defineClass; - private static final Method allocateInstance; - private static final Method putObject; - private static final Method objectFieldOffset; - - static - { - final Class<?> unsafeClass; - try { - unsafeClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() - { - @Override - public Class<?> run() - { - try - { - return Thread.currentThread().getContextClassLoader().loadClass("sun.misc.Unsafe"); - } - catch (Exception e) - { - try - { - return ClassLoader.getSystemClassLoader().loadClass("sun.misc.Unsafe"); - } - catch (ClassNotFoundException e1) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe", e); - } - } - } - }); - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe class", e); - } - - unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() - { - @Override - public Object run() - { - try - { - final Field field = unsafeClass.getDeclaredField("theUnsafe"); - field.setAccessible(true); - return field.get(null); - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe", e); - } - } - }); - allocateInstance = AccessController.doPrivileged(new PrivilegedAction<Method>() - { - @Override - public Method run() - { - try - { - final Method mtd = unsafeClass.getDeclaredMethod("allocateInstance", Class.class); - mtd.setAccessible(true); - return mtd; - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe.allocateInstance", e); - } - } - }); - objectFieldOffset = AccessController.doPrivileged(new PrivilegedAction<Method>() - { - @Override - public Method run() - { - try - { - final Method mtd = unsafeClass.getDeclaredMethod("objectFieldOffset", Field.class); - mtd.setAccessible(true); - return mtd; - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe.objectFieldOffset", e); - } - } - }); - putObject = AccessController.doPrivileged(new PrivilegedAction<Method>() - { - @Override - public Method run() - { - try - { - final Method mtd = unsafeClass.getDeclaredMethod("putObject", Object.class, long.class, Object.class); - mtd.setAccessible(true); - return mtd; - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe.putObject", e); - } - } - }); - defineClass = AccessController.doPrivileged(new PrivilegedAction<Method>() - { - @Override - public Method run() - { - try - { - final Method mtd = unsafeClass.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); - mtd.setAccessible(true); - return mtd; - } - catch (Exception e) - { - throw new IllegalStateException("Cannot get sun.misc.Unsafe.defineClass", e); - } - } - }); - } - - static Object allocateInstance(final Class<?> clazz) - { - try - { - return allocateInstance.invoke(unsafe, clazz); - } - catch (IllegalAccessException e) - { - throw new IllegalStateException("Failed to allocateInstance of Proxy class " + clazz.getName(), e); - } - catch (InvocationTargetException e) - { - final Throwable throwable = e.getTargetException() != null ? e.getTargetException() : e; - throw new IllegalStateException("Failed to allocateInstance of Proxy class " + clazz.getName(), throwable); - } - } - - static void setValue(final Field field, final Object object, final Object value) - { - final long offset; - try - { - offset = (Long) objectFieldOffset.invoke(unsafe, field); - } - catch (Exception e) - { - throw new IllegalStateException("Failed getting offset for: field=" + field.getName() + " class=" + field.getDeclaringClass().getName(), e); - } - - try - { - putObject.invoke(unsafe, object, offset, value); - } - catch (Exception e) - { - throw new IllegalStateException("Failed putting field=" + field.getName() + " class=" + field.getDeclaringClass().getName(), e); - } - } - - static Class<?> defineClass(final ClassLoader loader, final Class<?> clsToProxy, final String proxyName, final byte[] proxyBytes) throws IllegalAccessException, InvocationTargetException - { - return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes, 0, proxyBytes.length, loader, clsToProxy.getProtectionDomain()); - } - } } \ No newline at end of file Modified: commons/proper/proxy/branches/version-2.0-work/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/pom.xml?rev=1521303&r1=1521302&r2=1521303&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/pom.xml (original) +++ commons/proper/proxy/branches/version-2.0-work/pom.xml Mon Sep 9 22:27:27 2013 @@ -217,9 +217,14 @@ <version>3.0</version> </dependency> <dependency> - <groupId>org.apache.xbean</groupId> - <artifactId>xbean-asm4-shaded</artifactId> - <version>3.14</version> + <groupId>org.ow2.asm</groupId> + <artifactId>asm</artifactId> + <version>${asm.version}</version> + </dependency> + <dependency> + <groupId>org.ow2.asm</groupId> + <artifactId>asm-commons</artifactId> + <version>${asm.version}</version> </dependency> <dependency> <groupId>jmock</groupId> @@ -242,5 +247,6 @@ <commons.binary.suffix></commons.binary.suffix> <commons.jira.id>PROXY</commons.jira.id> <commons.jira.pid>12310731</commons.jira.pid> + <asm.version>4.1</asm.version> </properties> </project>