Top Description Inners Fields Constructors Methods
javassist.util.proxy

public Class ProxyFactory

extends Object
Class Inheritance
Imports
java.lang.ref.Reference, .WeakReference, java.lang.reflect.Constructor, .Field, .InvocationTargetException, .Member, .Method, .Modifier, java.security.ProtectionDomain, java.util.ArrayList, .Collections, .Comparator, .HashMap, .HashSet, .Iterator, .List, .Map, .Set, .WeakHashMap, java.lang.invoke.MethodHandles.Lookup, javassist.CannotCompileException, javassist.bytecode.AccessFlag, .Bytecode, .ClassFile, .CodeAttribute, .ConstPool, .Descriptor, .DuplicateMemberException, .ExceptionsAttribute, .FieldInfo, .MethodInfo, .Opcode, .SignatureAttribute, .StackMapTable

Factory of dynamic proxy classes.

This factory generates a class that extends the given super class and implements the given interfaces. The calls of the methods inherited from the super class are forwarded and then invoke() is called on the method handler associated with instances of the generated class. The calls of the methods from the interfaces are also forwarded to the method handler.

For example, if the following code is executed,

ProxyFactory f = new ProxyFactory();
f.setSuperclass(Foo.class);
f.setFilter(new MethodFilter() {
    public boolean isHandled(Method m) {
        // ignore finalize()
        return !m.getName().equals("finalize");
    }
});
Class c = f.createClass();
MethodHandler mi = new MethodHandler() {
    public Object invoke(Object self, Method m, Method proceed,
                         Object[] args) throws Throwable {
        System.out.println("Name: " + m.getName());
        return proceed.invoke(self, args);  // execute the original method.
    }
};
Foo foo = (Foo)c.newInstance();
((Proxy)foo).setHandler(mi);

Here, Method is java.lang.reflect.Method.

Then, the following method call will be forwarded to MethodHandler mi and prints a message before executing the originally called method bar() in Foo.

foo.bar();

The last three lines of the code shown above can be replaced with a call to the helper method create, which generates a proxy class, instantiates it, and sets the method handler of the instance:

    :
Foo foo = (Foo)f.create(new Class[0], new Object[0], mi);

To change the method handler during runtime, execute the following code:

MethodHandler mi = ... ;    // alternative handler
((Proxy)foo).setHandler(mi);

If setHandler is never called for a proxy instance then it will employ the default handler which proceeds by invoking the original method. The behaviour of the default handler is identical to the following handler:

class EmptyHandler implements MethodHandler {
    public Object invoke(Object self, Method m,
                         Method proceed, Object[] args) throws Exception {
        return proceed.invoke(self, args);
    }
}

A proxy factory caches and reuses proxy classes by default. It is possible to reset this default globally by setting static field ProxyFactory#useCache to false. Caching may also be configured for a specific factory by calling instance method ProxyFactory#setUseCache(boolean). It is strongly recommended that new clients of class ProxyFactory enable caching. Failure to do so may lead to exhaustion of the heap memory area used to store classes.

Caching is automatically disabled for any given proxy factory if deprecated instance method ProxyFactory#setHandler(MethodHandler) is called. This method was used to specify a default handler which newly created proxy classes should install when they create their instances. It is only retained to provide backward compatibility with previous releases of javassist. Unfortunately,this legacy behaviour makes caching and reuse of proxy classes impossible. The current programming model expects javassist clients to set the handler of a proxy instance explicitly by calling method Proxy#setHandler(MethodHandler) as shown in the sample code above. New clients are strongly recommended to use this model rather than calling ProxyFactory#setHandler(MethodHandler).

A proxy object generated by ProxyFactory is serializable if its super class or any of its interfaces implement java.io.Serializable. However, a serialized proxy object may not be compatible with future releases. The serialization support should be used for short-term storage or RMI.

For compatibility with older releases serialization of proxy objects is implemented by adding a writeReplace method to the proxy class. This allows a proxy to be serialized to a conventional java.io.ObjectOutputStream and deserialized from a corresponding java.io.ObjectInputStream. However this method suffers from several problems, the most notable one being that it fails to serialize state inherited from the proxy's superclass.

An alternative method of serializing proxy objects is available which fixes these problems. It requires inhibiting generation of the writeReplace method and instead using instances of javassist.util.proxy.ProxyObjectOutputStream and javassist.util.proxy.ProxyObjectInputStream (which are subclasses of java.io.ObjectOutputStream and java.io.ObjectInputStream) to serialize and deserialize, respectively, the proxy. These streams recognise javassist proxies and ensure that they are serialized and deserialized without the need for the proxy class to implement special methods such as writeReplace. Generation of the writeReplace method can be disabled globally by setting static field ProxyFactory#useWriteReplace to false. Alternatively, it may be configured per factory by calling instance method ProxyFactory#setUseWriteReplace(boolean).

Authors
Muga Nishizawa, Shigeru Chiba, Andrew Dinn
Since
3.1
See Also
MethodHandler

Nested and Inner Type Summary

Modifier and TypeClass and Description
public static interface
ProxyFactory.ClassLoaderProvider

A provider of class loaders.

pack-priv static class
pack-priv static class
ProxyFactory.ProxyDetails

used to store details of a specific proxy class in the second tier of the proxy cache.

public static interface
ProxyFactory.UniqueName

A unique class name generator.

Field Summary

Modifier and TypeField and Description
private String
public static ProxyFactory.ClassLoaderProvider
classLoaderProvider

A provider used by createClass() for obtaining a class loader.

private String
private static final String
private boolean
factoryUseCache

per factory setting initialised from current setting for useCache but able to be reset before each create call

private boolean
factoryWriteReplace

per factory setting initialised from current setting for useWriteReplace but able to be reset before each create call

private static final String
private static final String
private String
private MethodHandler
private static final String
private static final String
private static final String
private static final String
private static final String
private static final String
private static final String
private boolean
private static char[]
private static final String
private static final String
private Class<?>[]
private MethodFilter
public static ProxyFactory.UniqueName
nameGenerator

A unique class name generator.

private static final String
private static final Class<?>
public static boolean
onlyPublicMethods

If true, only public/protected methods are forwarded to a proxy object.

private static final String
private static Map<ClassLoader, Map<String, ProxyFactory.ProxyDetails>>
private static final String
private static final String
private static final long
private byte[]
private List<Map.Entry<String, Method>>
private static Comparator<Map.Entry<String, Method>>
private Class<?>
private String
private Class<?>
public static volatile boolean
useCache

If true, a generated proxy class is cached and it will be reused when generating the proxy class with the same properties is requested.

public static volatile boolean
useWriteReplace

If true, a generated proxy class will implement method writeReplace enabling serialization of its proxies to a conventional ObjectOutputStream.

public String
writeDirectory

If the value of this variable is not null, the class file of the generated proxy class is written under the directory specified by this variable.

Constructor Summary

AccessConstructor and Description
public
ProxyFactory()

Constructs a factory of proxy class.

Method Summary

Modifier and TypeMethod and Description
private static void
private static void
addGetter(String classname, ClassFile cf, ConstPool cp)

private static int
addLoad(Bytecode code, int n, Class<?> type)

private static int
addLoadParameters(Bytecode code, Class<?>[] params, int offset)

private static int
addReturn(Bytecode code, Class<?> type)

private static void
addSetter(String classname, ClassFile cf, ConstPool cp)

private static void
addUnwrapper(Bytecode code, Class<?> type)

private void
private static boolean
areParametersSame(Method method, Method targetMethod)

private static void
callFind2Methods(Bytecode code, String superMethod, String
might be null.
thisMethod
,
int index, String desc, int classVar, int arrayVar)

private void
private void
public Object
create(Class<?>[]
parameter types for a constructor.
paramTypes
,
Object[]
arguments passed to a constructor.
args
,
MethodHandler
the method handler for the proxy class.
mh
)

Creates a proxy class and returns an instance of that class.

public Object
create(Class<?>[]
parameter types for a constructor.
paramTypes
,
Object[]
arguments passed to a constructor.
args
)

Creates a proxy class and returns an instance of that class.

public Class<?>
createClass()

Generates a proxy class using the current filter.

public Class<?>
createClass(MethodFilter filter)

Generates a proxy class using the supplied filter.

pack-priv Class<?>
createClass(byte[] signature)

Generates a proxy class with a specific signature.

public Class<?>
createClass(MethodHandles.Lookup
used for loading the proxy class. It needs an appropriate right to invoke defineClass for the proxy class.
lookup
)

Generates a proxy class using the current filter.

public Class<?>
createClass(MethodHandles.Lookup
used for loading the proxy class. It needs an appropriate right to invoke defineClass for the proxy class.
lookup
,
MethodFilter
the filter.
filter
)

Generates a proxy class using the supplied filter.

pack-priv Class<?>
createClass(MethodHandles.Lookup
used for loading the proxy class. It needs an appropriate right to invoke defineClass for the proxy class.
lookup
,
byte[]
the signature.
signature
)

Generates a proxy class with a specific signature.

private Class<?>
private void
private void
private Class<?>
getClassInTheSamePackage()

Obtains a class belonging to the same package that the created proxy class belongs to.

protected ClassLoader
protected ClassLoader
protected ProtectionDomain
private static Object
getField(Class<?> clazz, String fieldName)

pack-priv static byte[]
public static MethodHandler

Returns:

the method handler.
getHandler
(Proxy
a proxy object.
p
)

Obtains the method handler of the given proxy object.

public Class<?>[]
getInterfaces()

Obtains the interfaces set by setInterfaces.

public String
getKey(Class<?> superClass, Class<?>[] interfaces, byte[] signature, boolean useWriteReplace)

private Map<String, Method>
getMethods(Class<?> superClass, Class<?>[] interfaceTypes)

private void
getMethods(Map<String, Method> hash, Class<?> clazz, Set<Class<?>> visitedClasses)

private static String
public Class<?>
getSuperclass()

Obtains the super class set by setSuperclass().

private void
installSignature(byte[] signature)

private Class<?>
invokespecialTarget(Class<?> declClass)

private static boolean
private static boolean
isDuplicated(int index, Method[] methods)

public static boolean

Returns:

true if the class is a javassist proxy class otherwise false
isProxyClass
(Class<?> cl)

determine if a class is a javassist proxy class

public boolean

Returns:

true if this factory uses the proxy cache otherwise false
isUseCache
()

test whether this factory uses the proxy cache

public boolean

Returns:

true if this factory installs a writeReplace method in created classes otherwise false
isUseWriteReplace
()

test whether this factory installs a writeReplace method in created classes

private static boolean
isVisible(int
the modifiers of the method.
mod
,
String from, Member meth)

Returns true if the method is visible from the package.

private static String
private ClassFile
make()

private static MethodInfo
makeConstructor(String thisClassName, Constructor<?> cons, ConstPool cp, Class<?> superClass, boolean doHandlerInit)

private void
makeConstructors(String thisClassName, ClassFile cf, ConstPool cp, String classname)

private MethodInfo
makeDelegator(Method meth, String desc, ConstPool cp, Class<?> declClass, String delegatorName)

private static MethodInfo
makeForwarder(String thisClassName, Method meth, String desc, ConstPool cp, Class<?> declClass, String
null if the original method is abstract.
delegatorName
,
int index, List<ProxyFactory.Find2MethodsArgs> forwarders)

private static void
makeParameterList(Bytecode code, Class<?>[] params)

private static String
makeProxyName(String classname)

private void
private static String
makeUniqueName(String name, List<Map.Entry<String, Method>> sortedMethods)

private static boolean
private static int
makeWrapper(Bytecode code, Class<?> type, int regno)

private static MethodInfo
private void
override(String thisClassname, Method meth, String prefix, int index, String desc, ClassFile cf, ConstPool cp, List<ProxyFactory.Find2MethodsArgs> forwarders)

private int
private void
setBit(byte[] signature, int idx)

private void
setField(String fieldName, Object value)

public void
setFilter(MethodFilter mf)

Sets a filter that selects the methods that will be controlled by a handler.

public void
setGenericSignature(String
a generic signature.
sig
)

Sets the generic signature for the proxy class.

public void
setHandler(MethodHandler mi)
Deprecated since 3.12 use of this method is incompatible with proxy class caching.

Sets the default invocation handler.

public void
setInterfaces(Class<?>[] ifs)

Sets the interfaces of a proxy class.

private static void
setInterfaces(ClassFile cf, Class<?>[] interfaces, Class<?> proxyClass)

public void
setSuperclass(Class<?> clazz)

Sets the super class of a proxy class.

private static void
private static void
setThrows(MethodInfo minfo, ConstPool cp, Class<?>[] exceptions)

public void
setUseCache(boolean
true if this factory should use the proxy cache and false if it should not use the cache
useCache
)

configure whether this factory should use the proxy cache

public void
setUseWriteReplace(boolean
true if this factory should add a writeReplace method to created classes and false if it should not add a writeReplace method
useWriteReplace
)

configure whether this factory should add a writeReplace method to created classes

private boolean
testBit(byte[] signature, int idx)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait