![JAR search and dependency download from the Maven repository](/logo.png)
com.alibaba.dubbo.common.bytecode.Proxy Maven / Gradle / Ivy
/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.common.bytecode;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;
import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;
/**
* Proxy.
*
* @author qian.lei
*/
public abstract class Proxy
{
private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);
private static final String PACKAGE_NAME = Proxy.class.getPackage().getName();
public static final InvocationHandler RETURN_NULL_INVOKER = new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args){ return null; }
};
public static final InvocationHandler THROW_UNSUPPORTED_INVOKER = new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args){ throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented."); }
};
private static final Map> ProxyCacheMap = new WeakHashMap>();
private static final Object PendingGenerationMarker = new Object();
/**
* Get proxy.
*
* @param ics interface class array.
* @return Proxy instance.
*/
public static Proxy getProxy(Class>... ics)
{
return getProxy(ClassHelper.getCallerClassLoader(Proxy.class), ics);
}
/**
* Get proxy.
* @param cl class loader.
* @param ics interface class array.
*
* @return Proxy instance.
*/
public static Proxy getProxy(ClassLoader cl, Class>... ics)
{
if( ics.length > 65535 )
throw new IllegalArgumentException("interface limit exceeded");
StringBuilder sb = new StringBuilder();
for(int i=0;i tmp = null;
try
{
tmp = Class.forName(itf, false, cl);
}
catch(ClassNotFoundException e)
{}
if( tmp != ics[i] )
throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
sb.append(itf).append(';');
}
// use interface class name list as key.
String key = sb.toString();
// get cache by class loader.
Map cache;
synchronized( ProxyCacheMap )
{
cache = ProxyCacheMap.get(cl);
if( cache == null )
{
cache = new HashMap();
ProxyCacheMap.put(cl, cache);
}
}
Proxy proxy = null;
synchronized( cache )
{
do
{
Object value = cache.get(key);
if( value instanceof Reference> )
{
proxy = (Proxy)((Reference>)value).get();
if( proxy != null )
return proxy;
}
if( value == PendingGenerationMarker )
{
try{ cache.wait(); }catch(InterruptedException e){}
}
else
{
cache.put(key, PendingGenerationMarker);
break;
}
}
while( true );
}
long id = PROXY_CLASS_COUNTER.getAndIncrement();
String pkg = null;
ClassGenerator ccp = null, ccm = null;
try
{
ccp = ClassGenerator.newInstance(cl);
Set worked = new HashSet();
List methods = new ArrayList();
for(int i=0;i rt = method.getReturnType();
Class>[] pts = method.getParameterTypes();
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
for(int j=0;j[]{ InvocationHandler.class }, new Class>[0], "handler=$1;");
ccp.addDefaultConstructor();
Class> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// create Proxy class.
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
ccm.setClassName(fcn);
ccm.addDefaultConstructor();
ccm.setSuperClass(Proxy.class);
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
Class> pc = ccm.toClass();
proxy = (Proxy)pc.newInstance();
}
catch(RuntimeException e)
{
throw e;
}
catch(Exception e)
{
throw new RuntimeException(e.getMessage(), e);
}
finally
{
// release ClassGenerator
if( ccp != null )
ccp.release();
if( ccm != null )
ccm.release();
synchronized( cache )
{
if( proxy == null )
cache.remove(key);
else
cache.put(key, new WeakReference(proxy));
cache.notifyAll();
}
}
return proxy;
}
/**
* get instance with default handler.
*
* @return instance.
*/
public Object newInstance()
{
return newInstance(THROW_UNSUPPORTED_INVOKER);
}
/**
* get instance with special handler.
*
* @return instance.
*/
abstract public Object newInstance(InvocationHandler handler);
protected Proxy(){}
private static String asArgument(Class> cl, String name)
{
if( cl.isPrimitive() )
{
if( Boolean.TYPE == cl )
return name + "==null?false:((Boolean)" + name + ").booleanValue()";
if( Byte.TYPE == cl )
return name + "==null?(byte)0:((Byte)" + name + ").byteValue()";
if( Character.TYPE == cl )
return name + "==null?(char)0:((Character)" + name + ").charValue()";
if( Double.TYPE == cl )
return name + "==null?(double)0:((Double)" + name + ").doubleValue()";
if( Float.TYPE == cl )
return name + "==null?(float)0:((Float)" + name + ").floatValue()";
if( Integer.TYPE == cl )
return name + "==null?(int)0:((Integer)" + name + ").intValue()";
if( Long.TYPE == cl )
return name + "==null?(long)0:((Long)" + name + ").longValue()";
if( Short.TYPE == cl )
return name + "==null?(short)0:((Short)" + name + ").shortValue()";
throw new RuntimeException(name+" is unknown primitive type.");
}
return "(" + ReflectUtils.getName(cl) + ")"+name;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy