classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: java.lang.reflect.Proxy


From: Eric Blake
Subject: RE: java.lang.reflect.Proxy
Date: Fri, 3 Aug 2001 04:12:40 +0100

I've already stayed up late tonight hacking out ideas.  It looks like only
getProxyClass would need to be native; everything else is simple enough to
do in pure Java.  With getProxyClass, I see two reasonable places to defer
to native code:

1. Argument validation - it takes quite a bit of reflection to deduce things
like compatible throws clauses, and since reflection already involves native
calls, the VM can probably do it faster.
2. Class generation - given the set of interfaces to extend and methods to
implement, generate the proper Class object.  Here, a native implementation
need not necessarily even generate bytecode, but could instead directly
create the Class object and correctly populate the method dispatch table or
whatever else it uses.

Either one could be done natively while the other remains in Java, or a
native version could do both in one shot.  So, this is my pseudocode
version:

package java.lang.reflect;
import gnu.classpath.Configuration;
public class Proxy
{
  /** A struct for holding all information needed to generate a proxy class
*/
  static class ProxyData
  {
    Package pack; // package the proxy class belongs to
    Class[] interfaces; // implemented interfaces
    Method[] methods; // the method objects to pass to InvocationHandler
    Class[][] exceptions; // array of exceptions thrown by each method
(exceptions[i] is the same as or a subset of methods[i].getExceptionTypes())
    int id; // unique id for this proxy class
    //... anything else I need
  }

  /** Javadoc... */
  public static synchronized Class getProxyClass(ClassLoader cl, Class[]
interfaces)
  {
    Class clazz = lookup(cl, interfaces); // has this combo already been
seen?
    if (clazz != null)
      return clazz;

    if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS)
      {
        clazz = getProxyClass0(cl, interfaces);
        return store(clazz);
      }

    ProxyData data = getProxyData(cl, interfaces);
    clazz = generateProxyClass(cl, data);
    return store(clazz);
  }
  /** Do it all; this is guaranteed to be called only once per cl/interfaces
combination */
  private static native Class getProxyClass0(ClassLoader cl, Class[]
interfaces);

  /** set up a ProxyData object, while validating arguments.
   * @throws IllegalArgumentException, NullPointerException as per specs
   */
  private static ProxyData getProxyData(ClassLoader cl, Class[] interfaces)
  {
    if (Configuration.HAVE_NATIVE_GET_PROXY_DATA)
      return getProxyData0(cl, interfaces);
    ProxyData data = new ProxyData();
    // validate arguments, populate data by reflection
    return data;
  }
  private static native ProxyData getProxyData0(ClassLoader cl, Class[]
interfaces);

  /** convert a ProxyData object into a Class object.  At this point,
   * all data is valid, so the only exception might be OutOfMemoryError
   * or the like.
   */
  private static Class generateProxyClass(ClassLoader cl, ProxyData data)
  {
    if (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS)
      return generateProxyClass0(cl, data);
    byte[] bytecode;
    // write header
    // for each method in data.methods, generate bytecode from boilerplate
    // put it all together, and...
    VMClassLoader.defineClass(cl, name, bytecode, ...);
  }
  private static native Class generateProxyClass0(ClassLoader cl, ProxyData
data);
}

--
Eric Blake, Elixent, Castlemead, Lwr Castle St., Bristol BS1 3AG, UK
address@hidden   tel:+44(0)117 917 5611


> -----Original Message-----
> From: address@hidden
> [mailto:address@hidden Behalf Of Stuart Ballard
> Sent: 03 August 2001 03:04
> To: Eric Blake
> Cc: address@hidden
> Subject: Re: java.lang.reflect.Proxy
>
> > To do this in pure Java, I plan to generate a byte[] on the fly
> that will
> > then be loaded as a class by the appropriate ClassLoader.
>
> This seems a somewhat kludgy way of doing it, although I agree it's
> probably the only way to do it without specific VM support. Perhaps it
> would be possible to write this in a way that would allow a simpler (and
> possibly faster) VM-supported mechanism to be plugged in later?
>
> Stuart.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]