[Soot-list] a problem on soot method
zhou yuming
cs.zhou.yuming at gmail.com
Thu Aug 16 20:08:46 EDT 2007
Hi,
In the class "ClassMap", there are two methods with the same name but
different parameters:
private static Method[] getAccessibleMethods(Class clazz)
private static int getAccessibleMethods( Class clazz, MethodInfo[]
methodInfos, int upcastCount)
According to my understanding, the corresponding sootclass should contain
both methods. However, I found that only the first method was included. I
do not understand why the sootclass excluded the second method. Whatever
soot 2.1.0 or 2.2.1 is used, the result is the same.
Could you please give me a hand? Thanks
Zhouyuming
The sootmethods in the soot class:
<ClassMap: void <clinit>()>
<ClassMap: void <init>(java.lang.Class)>
<ClassMap: java.lang.Class getCachedClass()>
<ClassMap: java.lang.reflect.Method findMethod(java.lang.String,
java.lang.Object[])>
<ClassMap: void populateMethodCache()>
<ClassMap: java.lang.String makeMethodKey(java.lang.reflect.Method)>
<ClassMap: java.lang.String makeMethodKey(java.lang.String,java.lang.Object
[])>
<ClassMap: java.lang.reflect.Method[] getAccessibleMethods(java.lang.Class)>
<ClassMap: java.lang.reflect.Method getPublicMethod(java.lang.reflect.Method
)>
<ClassMap: java.lang.reflect.Method getPublicMethod(java.lang.Class,
java.lang.String,java.lang.Class[])>
-----------------------------------
import java.util.Map;
import java.util.List;
import java.util.Hashtable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ClassMap
{
private static final class CacheMiss { }
private static final CacheMiss CACHE_MISS = new CacheMiss();
private static final Object OBJECT = new Object();
private Class clazz;
private Map methodCache = new Hashtable();
private MethodMap methodMap = new MethodMap();
public ClassMap(Class clazz)
{
this.clazz = clazz;
populateMethodCache();
}
Class getCachedClass()
{
return clazz;
}
public Method findMethod(String name, Object[] params)
{
String methodKey = makeMethodKey(name, params);
Object cacheEntry = methodCache.get( methodKey );
if (cacheEntry == CACHE_MISS)
{
return null;
}
if (cacheEntry == null)
{
cacheEntry = methodMap.find( name,
params );
if ( cacheEntry == null )
{
methodCache.put( methodKey,
CACHE_MISS );
}
else
{
methodCache.put( methodKey,
cacheEntry );
}
}
// Yes, this might just be null.
return (Method) cacheEntry;
}
private void populateMethodCache()
{
StringBuffer methodKey;
Method[] methods = getAccessibleMethods(clazz);
for (int i = 0; i < methods.length; i++)
{
Method method = methods[i];
Method publicMethod = getPublicMethod( method );
if ( publicMethod != null)
{
methodMap.add( publicMethod );
methodCache.put( makeMethodKey( publicMethod),
publicMethod);
}
}
}
private String makeMethodKey(Method method)
{
Class[] parameterTypes = method.getParameterTypes();
StringBuffer methodKey = new StringBuffer().append(method.getName
());
for (int j = 0; j < parameterTypes.length; j++)
{
if (parameterTypes[j].isPrimitive())
{
if (parameterTypes[j].equals(Boolean.TYPE))
methodKey.append("java.lang.Boolean");
else if (parameterTypes[j].equals(Byte.TYPE))
methodKey.append("java.lang.Byte");
else if (parameterTypes[j].equals(Character.TYPE))
methodKey.append("java.lang.Character");
else if (parameterTypes[j].equals(Double.TYPE))
methodKey.append("java.lang.Double");
else if (parameterTypes[j].equals(Float.TYPE))
methodKey.append("java.lang.Float");
else if (parameterTypes[j].equals(Integer.TYPE))
methodKey.append("java.lang.Integer");
else if (parameterTypes[j].equals(Long.TYPE))
methodKey.append("java.lang.Long");
else if (parameterTypes[j].equals(Short.TYPE))
methodKey.append("java.lang.Short");
}
else
methodKey.append(parameterTypes[j].getName());
}
return methodKey.toString();
}
private static String makeMethodKey(String method, Object[] params)
{
StringBuffer methodKey = new StringBuffer().append(method);
for (int j = 0; j < params.length; j++)
{
if (params[j] == null)
params[j] = OBJECT;
methodKey.append(params[j].getClass().getName());
}
return methodKey.toString();
}
private static Method[] getAccessibleMethods(Class clazz)
{
Method[] methods = clazz.getMethods();
if (Modifier.isPublic(clazz.getModifiers()))
{
return methods;
}
MethodInfo[] methodInfos = new MethodInfo[methods.length];
for(int i = methods.length; i-- > 0; )
{
methodInfos[i] = new MethodInfo(methods[i]);
}
int upcastCount = getAccessibleMethods(clazz, methodInfos, 0);
if(upcastCount < methods.length)
{
methods = new Method[upcastCount];
}
int j = 0;
for(int i = 0; i < methodInfos.length; ++i)
{
MethodInfo methodInfo = methodInfos[i];
if(methodInfo.upcast)
{
methods[j++] = methodInfo.method;
}
}
return methods;
}
private static int getAccessibleMethods( Class clazz, MethodInfo[]
methodInfos, int upcastCount)
{
int l = methodInfos.length;
if( Modifier.isPublic(clazz.getModifiers()) )
{
for(int i = 0; i < l && upcastCount < l; ++i)
{
try
{
MethodInfo methodInfo = methodInfos[i];
if(!methodInfo.upcast)
{
methodInfo.tryUpcasting(clazz);
}
upcastCount++;
}
catch(NoSuchMethodException e)
{
}
}
if(upcastCount == l)
{
return upcastCount;
}
}
Class superclazz = clazz.getSuperclass();
if(superclazz != null)
{
upcastCount = getAccessibleMethods(superclazz , methodInfos,
upcastCount);
if(upcastCount == l)
{
return upcastCount;
}
}
Class[] interfaces = clazz.getInterfaces();
for(int i = interfaces.length; i-- > 0; )
{
upcastCount = getAccessibleMethods(interfaces[i], methodInfos,
upcastCount);
if(upcastCount == l)
{
return upcastCount;
}
}
return upcastCount;
}
public static Method getPublicMethod(Method method)
{
Class clazz = method.getDeclaringClass();
/*
* Short circuit for (hopefully the majority of) cases where the
declaring
* class is public.
*/
if((clazz.getModifiers() & Modifier.PUBLIC) != 0)
{
return method;
}
return getPublicMethod(clazz, method.getName(),
method.getParameterTypes());
}
private static Method getPublicMethod(Class clazz, String name, Class[]
paramTypes)
{
if((clazz.getModifiers() & Modifier.PUBLIC) != 0)
{
try
{
return clazz.getMethod(name, paramTypes);
}
catch(NoSuchMethodException e)
{
return null;
}
}
Class superclazz = clazz.getSuperclass();
if ( superclazz != null )
{
Method superclazzMethod = getPublicMethod(superclazz, name,
paramTypes);
if(superclazzMethod != null)
{
return superclazzMethod;
}
}
Class[] interfaces = clazz.getInterfaces();
for(int i = 0; i < interfaces.length; ++i)
{
Method interfaceMethod = getPublicMethod(interfaces[i], name,
paramTypes);
if(interfaceMethod != null)
{
return interfaceMethod;
}
}
return null;
}
private static final class MethodInfo
{
Method method;
String name;
Class[] parameterTypes;
boolean upcast;
MethodInfo(Method method)
{
this.method = null;
name = method.getName();
parameterTypes = method.getParameterTypes();
upcast = false;
}
void tryUpcasting(Class clazz)
throws NoSuchMethodException
{
method = clazz.getMethod(name, parameterTypes);
name = null;
parameterTypes = null;
upcast = true;
}
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20070817/6ac8ad5b/attachment-0001.htm
More information about the Soot-list
mailing list