emul/mini/src/main/java/java/lang/reflect/Proxy.java
branchemul
changeset 604 3fcc279c921b
parent 601 5198affdb915
     1.1 --- a/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Mon Jan 28 18:12:47 2013 +0100
     1.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Mon Jan 28 18:15:21 2013 +0100
     1.3 @@ -25,17 +25,6 @@
     1.4  
     1.5  package java.lang.reflect;
     1.6  
     1.7 -import java.lang.ref.Reference;
     1.8 -import java.lang.ref.WeakReference;
     1.9 -import java.util.Arrays;
    1.10 -import java.util.Collections;
    1.11 -import java.util.HashMap;
    1.12 -import java.util.HashSet;
    1.13 -import java.util.Map;
    1.14 -import java.util.Set;
    1.15 -import java.util.List;
    1.16 -import java.util.WeakHashMap;
    1.17 -import sun.misc.ProxyGenerator;
    1.18  
    1.19  /**
    1.20   * {@code Proxy} provides static methods for creating dynamic proxy
    1.21 @@ -223,27 +212,7 @@
    1.22  
    1.23      private static final long serialVersionUID = -2222568056686623797L;
    1.24  
    1.25 -    /** prefix for all proxy class names */
    1.26 -    private final static String proxyClassNamePrefix = "$Proxy";
    1.27  
    1.28 -    /** parameter types of a proxy class constructor */
    1.29 -    private final static Class[] constructorParams =
    1.30 -        { InvocationHandler.class };
    1.31 -
    1.32 -    /** maps a class loader to the proxy class cache for that loader */
    1.33 -    private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
    1.34 -        = new WeakHashMap<>();
    1.35 -
    1.36 -    /** marks that a particular proxy class is currently being generated */
    1.37 -    private static Object pendingGenerationMarker = new Object();
    1.38 -
    1.39 -    /** next number to use for generation of unique proxy class names */
    1.40 -    private static long nextUniqueNumber = 0;
    1.41 -    private static Object nextUniqueNumberLock = new Object();
    1.42 -
    1.43 -    /** set of all generated proxy classes, for isProxyClass implementation */
    1.44 -    private static Map<Class<?>, Void> proxyClasses =
    1.45 -        Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
    1.46  
    1.47      /**
    1.48       * the invocation handler for this proxy instance.
    1.49 @@ -346,215 +315,7 @@
    1.50                                           Class<?>... interfaces)
    1.51          throws IllegalArgumentException
    1.52      {
    1.53 -        if (interfaces.length > 65535) {
    1.54 -            throw new IllegalArgumentException("interface limit exceeded");
    1.55 -        }
    1.56 -
    1.57 -        Class<?> proxyClass = null;
    1.58 -
    1.59 -        /* collect interface names to use as key for proxy class cache */
    1.60 -        String[] interfaceNames = new String[interfaces.length];
    1.61 -
    1.62 -        // for detecting duplicates
    1.63 -        Set<Class<?>> interfaceSet = new HashSet<>();
    1.64 -
    1.65 -        for (int i = 0; i < interfaces.length; i++) {
    1.66 -            /*
    1.67 -             * Verify that the class loader resolves the name of this
    1.68 -             * interface to the same Class object.
    1.69 -             */
    1.70 -            String interfaceName = interfaces[i].getName();
    1.71 -            Class<?> interfaceClass = null;
    1.72 -            try {
    1.73 -                interfaceClass = Class.forName(interfaceName, false, loader);
    1.74 -            } catch (ClassNotFoundException e) {
    1.75 -            }
    1.76 -            if (interfaceClass != interfaces[i]) {
    1.77 -                throw new IllegalArgumentException(
    1.78 -                    interfaces[i] + " is not visible from class loader");
    1.79 -            }
    1.80 -
    1.81 -            /*
    1.82 -             * Verify that the Class object actually represents an
    1.83 -             * interface.
    1.84 -             */
    1.85 -            if (!interfaceClass.isInterface()) {
    1.86 -                throw new IllegalArgumentException(
    1.87 -                    interfaceClass.getName() + " is not an interface");
    1.88 -            }
    1.89 -
    1.90 -            /*
    1.91 -             * Verify that this interface is not a duplicate.
    1.92 -             */
    1.93 -            if (interfaceSet.contains(interfaceClass)) {
    1.94 -                throw new IllegalArgumentException(
    1.95 -                    "repeated interface: " + interfaceClass.getName());
    1.96 -            }
    1.97 -            interfaceSet.add(interfaceClass);
    1.98 -
    1.99 -            interfaceNames[i] = interfaceName;
   1.100 -        }
   1.101 -
   1.102 -        /*
   1.103 -         * Using string representations of the proxy interfaces as
   1.104 -         * keys in the proxy class cache (instead of their Class
   1.105 -         * objects) is sufficient because we require the proxy
   1.106 -         * interfaces to be resolvable by name through the supplied
   1.107 -         * class loader, and it has the advantage that using a string
   1.108 -         * representation of a class makes for an implicit weak
   1.109 -         * reference to the class.
   1.110 -         */
   1.111 -        List<String> key = Arrays.asList(interfaceNames);
   1.112 -
   1.113 -        /*
   1.114 -         * Find or create the proxy class cache for the class loader.
   1.115 -         */
   1.116 -        Map<List<String>, Object> cache;
   1.117 -        synchronized (loaderToCache) {
   1.118 -            cache = loaderToCache.get(loader);
   1.119 -            if (cache == null) {
   1.120 -                cache = new HashMap<>();
   1.121 -                loaderToCache.put(loader, cache);
   1.122 -            }
   1.123 -            /*
   1.124 -             * This mapping will remain valid for the duration of this
   1.125 -             * method, without further synchronization, because the mapping
   1.126 -             * will only be removed if the class loader becomes unreachable.
   1.127 -             */
   1.128 -        }
   1.129 -
   1.130 -        /*
   1.131 -         * Look up the list of interfaces in the proxy class cache using
   1.132 -         * the key.  This lookup will result in one of three possible
   1.133 -         * kinds of values:
   1.134 -         *     null, if there is currently no proxy class for the list of
   1.135 -         *         interfaces in the class loader,
   1.136 -         *     the pendingGenerationMarker object, if a proxy class for the
   1.137 -         *         list of interfaces is currently being generated,
   1.138 -         *     or a weak reference to a Class object, if a proxy class for
   1.139 -         *         the list of interfaces has already been generated.
   1.140 -         */
   1.141 -        synchronized (cache) {
   1.142 -            /*
   1.143 -             * Note that we need not worry about reaping the cache for
   1.144 -             * entries with cleared weak references because if a proxy class
   1.145 -             * has been garbage collected, its class loader will have been
   1.146 -             * garbage collected as well, so the entire cache will be reaped
   1.147 -             * from the loaderToCache map.
   1.148 -             */
   1.149 -            do {
   1.150 -                Object value = cache.get(key);
   1.151 -                if (value instanceof Reference) {
   1.152 -                    proxyClass = (Class<?>) ((Reference) value).get();
   1.153 -                }
   1.154 -                if (proxyClass != null) {
   1.155 -                    // proxy class already generated: return it
   1.156 -                    return proxyClass;
   1.157 -                } else if (value == pendingGenerationMarker) {
   1.158 -                    // proxy class being generated: wait for it
   1.159 -                    try {
   1.160 -                        cache.wait();
   1.161 -                    } catch (InterruptedException e) {
   1.162 -                        /*
   1.163 -                         * The class generation that we are waiting for should
   1.164 -                         * take a small, bounded time, so we can safely ignore
   1.165 -                         * thread interrupts here.
   1.166 -                         */
   1.167 -                    }
   1.168 -                    continue;
   1.169 -                } else {
   1.170 -                    /*
   1.171 -                     * No proxy class for this list of interfaces has been
   1.172 -                     * generated or is being generated, so we will go and
   1.173 -                     * generate it now.  Mark it as pending generation.
   1.174 -                     */
   1.175 -                    cache.put(key, pendingGenerationMarker);
   1.176 -                    break;
   1.177 -                }
   1.178 -            } while (true);
   1.179 -        }
   1.180 -
   1.181 -        try {
   1.182 -            String proxyPkg = null;     // package to define proxy class in
   1.183 -
   1.184 -            /*
   1.185 -             * Record the package of a non-public proxy interface so that the
   1.186 -             * proxy class will be defined in the same package.  Verify that
   1.187 -             * all non-public proxy interfaces are in the same package.
   1.188 -             */
   1.189 -            for (int i = 0; i < interfaces.length; i++) {
   1.190 -                int flags = interfaces[i].getModifiers();
   1.191 -                if (!Modifier.isPublic(flags)) {
   1.192 -                    String name = interfaces[i].getName();
   1.193 -                    int n = name.lastIndexOf('.');
   1.194 -                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
   1.195 -                    if (proxyPkg == null) {
   1.196 -                        proxyPkg = pkg;
   1.197 -                    } else if (!pkg.equals(proxyPkg)) {
   1.198 -                        throw new IllegalArgumentException(
   1.199 -                            "non-public interfaces from different packages");
   1.200 -                    }
   1.201 -                }
   1.202 -            }
   1.203 -
   1.204 -            if (proxyPkg == null) {     // if no non-public proxy interfaces,
   1.205 -                proxyPkg = "";          // use the unnamed package
   1.206 -            }
   1.207 -
   1.208 -            {
   1.209 -                /*
   1.210 -                 * Choose a name for the proxy class to generate.
   1.211 -                 */
   1.212 -                long num;
   1.213 -                synchronized (nextUniqueNumberLock) {
   1.214 -                    num = nextUniqueNumber++;
   1.215 -                }
   1.216 -                String proxyName = proxyPkg + proxyClassNamePrefix + num;
   1.217 -                /*
   1.218 -                 * Verify that the class loader hasn't already
   1.219 -                 * defined a class with the chosen name.
   1.220 -                 */
   1.221 -
   1.222 -                /*
   1.223 -                 * Generate the specified proxy class.
   1.224 -                 */
   1.225 -                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
   1.226 -                    proxyName, interfaces);
   1.227 -                try {
   1.228 -                    proxyClass = defineClass0(loader, proxyName,
   1.229 -                        proxyClassFile, 0, proxyClassFile.length);
   1.230 -                } catch (ClassFormatError e) {
   1.231 -                    /*
   1.232 -                     * A ClassFormatError here means that (barring bugs in the
   1.233 -                     * proxy class generation code) there was some other
   1.234 -                     * invalid aspect of the arguments supplied to the proxy
   1.235 -                     * class creation (such as virtual machine limitations
   1.236 -                     * exceeded).
   1.237 -                     */
   1.238 -                    throw new IllegalArgumentException(e.toString());
   1.239 -                }
   1.240 -            }
   1.241 -            // add to set of all generated proxy classes, for isProxyClass
   1.242 -            proxyClasses.put(proxyClass, null);
   1.243 -
   1.244 -        } finally {
   1.245 -            /*
   1.246 -             * We must clean up the "pending generation" state of the proxy
   1.247 -             * class cache entry somehow.  If a proxy class was successfully
   1.248 -             * generated, store it in the cache (with a weak reference);
   1.249 -             * otherwise, remove the reserved entry.  In all cases, notify
   1.250 -             * all waiters on reserved entries in this cache.
   1.251 -             */
   1.252 -            synchronized (cache) {
   1.253 -                if (proxyClass != null) {
   1.254 -                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
   1.255 -                } else {
   1.256 -                    cache.remove(key);
   1.257 -                }
   1.258 -                cache.notifyAll();
   1.259 -            }
   1.260 -        }
   1.261 -        return proxyClass;
   1.262 +        throw new IllegalArgumentException();
   1.263      }
   1.264  
   1.265      /**
   1.266 @@ -594,27 +355,7 @@
   1.267          if (h == null) {
   1.268              throw new NullPointerException();
   1.269          }
   1.270 -
   1.271 -        /*
   1.272 -         * Look up or generate the designated proxy class.
   1.273 -         */
   1.274 -        Class<?> cl = getProxyClass(loader, interfaces);
   1.275 -
   1.276 -        /*
   1.277 -         * Invoke its constructor with the designated invocation handler.
   1.278 -         */
   1.279 -        try {
   1.280 -            Constructor cons = cl.getConstructor(constructorParams);
   1.281 -            return cons.newInstance(new Object[] { h });
   1.282 -        } catch (NoSuchMethodException e) {
   1.283 -            throw new InternalError(e.toString());
   1.284 -        } catch (IllegalAccessException e) {
   1.285 -            throw new InternalError(e.toString());
   1.286 -        } catch (InstantiationException e) {
   1.287 -            throw new InternalError(e.toString());
   1.288 -        } catch (InvocationTargetException e) {
   1.289 -            throw new InternalError(e.toString());
   1.290 -        }
   1.291 +        throw new IllegalArgumentException();
   1.292      }
   1.293  
   1.294      /**
   1.295 @@ -636,7 +377,7 @@
   1.296              throw new NullPointerException();
   1.297          }
   1.298  
   1.299 -        return proxyClasses.containsKey(cl);
   1.300 +        return false;
   1.301      }
   1.302  
   1.303      /**