diff options
author | Dennis Wagelaar | 2017-04-27 13:17:29 +0000 |
---|---|---|
committer | Dennis Wagelaar | 2017-04-27 13:17:29 +0000 |
commit | c8f39fd70b0f8d5f50fdc789cd0148da88e21483 (patch) | |
tree | 9526f0e4c248d18d111faaf5bd062124d48f18e8 /plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl | |
parent | fc7cf94070cba2716d4967f636b26071d25ae56c (diff) | |
download | org.eclipse.atl-c8f39fd70b0f8d5f50fdc789cd0148da88e21483.tar.gz org.eclipse.atl-c8f39fd70b0f8d5f50fdc789cd0148da88e21483.tar.xz org.eclipse.atl-c8f39fd70b0f8d5f50fdc789cd0148da88e21483.zip |
488223: EMFTVMUtil#getMethodSignature() causes method lookup collisions
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=488223
Diffstat (limited to 'plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl')
2 files changed, 270 insertions, 180 deletions
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java index dc67540c..67f09e76 100644 --- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java +++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/EMFTVMUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011-2015 Dennis Wagelaar, Vrije Universiteit Brussel. + * Copyright (c) 2011-2017 Dennis Wagelaar, Vrije Universiteit Brussel. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,6 +17,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -25,7 +26,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -34,6 +34,8 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.regex.Pattern; import org.eclipse.emf.common.util.EList; @@ -157,7 +159,12 @@ public final class EMFTVMUtil { * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - private static final Map<Class<?>, Map<MethodSignature, Method>> METHOD_CACHE = new WeakHashMap<Class<?>, Map<MethodSignature, Method>>(); + private static final ConcurrentMap<MethodSignature, WeakReference<Method>> METHOD_CACHE = new ConcurrentHashMap<MethodSignature, WeakReference<Method>>(); + + /** + * Represents the <code>null</code> method reference for the {@link #METHOD_CACHE}. + */ + private static final WeakReference<Method> NULL_METHOD_REFERENCE = new WeakReference<Method>(null); /** * Cache used to store the found root methods for native Java methods. @@ -167,7 +174,8 @@ public final class EMFTVMUtil { * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - private static final Map<Method, Method> ROOT_METHOD_CACHE = Collections.synchronizedMap(new WeakHashMap<Method, Method>()); + private static final Map<Method, WeakReference<Method>> ROOT_METHOD_CACHE = Collections + .synchronizedMap(new WeakHashMap<Method, WeakReference<Method>>()); /** * Singleton {@link RegistryTypeSwitch} instance. @@ -178,6 +186,11 @@ public final class EMFTVMUtil { private static Metamodel emfTvmMetamodel; private static Metamodel traceMetamodel; + private static volatile int MethodCacheAccesses; + private static volatile int MethodCacheHits; + private static volatile int RootMethodCacheAccesses; + private static volatile int RootMethodCacheHits; + /** * Not used. */ @@ -1400,7 +1413,7 @@ public final class EMFTVMUtil { * The class of the method * @param opname * The method name - * @param argumentTypes + * @param argTypes * The types of all arguments * @param isStatic * Whether to look for a static method or not @@ -1410,18 +1423,108 @@ public final class EMFTVMUtil { * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - // TODO implement multi-methods in ExecEnv public static Method findNativeMethod(final Class<?> context, final String opname, final Class<?>[] argTypes, final boolean isStatic) { if (context == Void.TYPE) { return null; // Java methods cannot be invoked on null, or defined on Void } - final MethodSignature sig = getMethodSignature(opname, argTypes, isStatic); - Method ret = findCachedMethod(context, sig); - if (ret != null || hasCachedMethod(context, sig)) { + final MethodSignature sig = getMethodSignature(context, opname, argTypes, isStatic); + MethodCacheAccesses++; + final WeakReference<Method> methodRef = METHOD_CACHE.get(sig); + final Method ret = methodRef != null ? methodRef.get() : null; + if (ret != null || methodRef == NULL_METHOD_REFERENCE) { + MethodCacheHits++; + return methodRef.get(); + } + + return findNativeMethodInternal(context, opname, argTypes, isStatic, sig); + } + + /** + * Looks for a native Java method. + * + * @param context + * The class of the method + * @param opname + * The method name + * @param argumentType + * The type of the argument + * @param isStatic + * Whether to look for a static method or not + * @return the method if found, null otherwise + * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> + * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> + * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> + * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> + */ + public static Method findNativeMethod(final Class<?> context, final String opname, final Class<?> argType, final boolean isStatic) { + if (context == Void.TYPE) { + return null; // Java methods cannot be invoked on null, or defined on Void + } + + final MethodSignature sig = getMethodSignature(context, opname, argType, isStatic); + MethodCacheAccesses++; + final WeakReference<Method> methodRef = METHOD_CACHE.get(sig); + final Method ret = methodRef != null ? methodRef.get() : null; + if (ret != null || methodRef == NULL_METHOD_REFERENCE) { + MethodCacheHits++; return ret; } + return findNativeMethodInternal(context, opname, argType, isStatic, sig); + } + + /** + * Looks for a native Java method without arguments. + * + * @param context + * The class of the method + * @param opname + * The method name + * @param isStatic + * Whether to look for a static method or not + * @return the method if found, null otherwise + * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> + * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> + * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> + * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> + */ + public static Method findNativeMethod(final Class<?> context, final String opname, final boolean isStatic) { + if (context == Void.TYPE) { + return null; // Java methods cannot be invoked on null, or defined on Void + } + + final MethodSignature sig = getMethodSignature(context, opname, isStatic); + MethodCacheAccesses++; + final WeakReference<Method> methodRef = METHOD_CACHE.get(sig); + Method ret = methodRef != null ? methodRef.get() : null; + if (ret != null || methodRef == NULL_METHOD_REFERENCE) { + MethodCacheHits++; + return ret; + } + + return findNativeMethodInternal(context, opname, isStatic, sig); + } + + /** + * Looks for a native Java method. + * + * @param context + * The class of the method + * @param opname + * The method name + * @param argTypes + * The types of all arguments + * @param isStatic + * Whether to look for a static method or not + * @param sig + * the method signature + * @return the method if found, null otherwise + */ + private static Method findNativeMethodInternal(final Class<?> context, final String opname, + final Class<?>[] argTypes, final boolean isStatic, final MethodSignature sig) { + Method ret = null; + final Method[] methods = context.getDeclaredMethods(); METHODS: for (int i = 0; i < methods.length; i++) { Method method = methods[i]; @@ -1430,24 +1533,9 @@ public final class EMFTVMUtil { if (pts.length == argTypes.length) { boolean ok = true; for (int j = 0; (j < pts.length) && ok; j++) { - if (argTypes[j] == EnumLiteral.class && Enumerator.class.isAssignableFrom(pts[j])) { - continue; - } - if (!pts[j].isAssignableFrom(argTypes[j])) { - if (pts[j] == boolean.class) - ok = argTypes[j] == Boolean.class; - else if (pts[j] == int.class) - ok = argTypes[j] == Integer.class; - else if (pts[j] == char.class) - ok = argTypes[j] == Character.class; - else if (pts[j] == long.class) - ok = argTypes[j] == Long.class; - else if (pts[j] == float.class) - ok = argTypes[j] == Float.class; - else if (pts[j] == double.class) - ok = argTypes[j] == Double.class; - else - ok = argTypes[j] == Void.TYPE; // any type + if (!checkParameterType(argTypes[j], pts[j])) { + ok = false; + break; } } if (ok) { @@ -1457,13 +1545,13 @@ public final class EMFTVMUtil { } } } - + if ((ret == null) && !isStatic && (context.getSuperclass() != null)) { - ret = findNativeMethod(context.getSuperclass(), opname, argTypes, isStatic); + ret = findNativeMethodInternal(context.getSuperclass(), opname, argTypes, isStatic, sig); + } else { + METHOD_CACHE.put(sig, ret != null ? new WeakReference<Method>(ret) : NULL_METHOD_REFERENCE); } - - cacheMethod(context, sig, ret); - + return ret; } @@ -1474,70 +1562,38 @@ public final class EMFTVMUtil { * The class of the method * @param opname * The method name - * @param argumentType + * @param argType * The type of the argument * @param isStatic * Whether to look for a static method or not + * @param sig + * the method signature * @return the method if found, null otherwise - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> - * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> - * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> - * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - // TODO implement multi-methods in ExecEnv - public static Method findNativeMethod(final Class<?> context, final String opname, final Class<?> argType, final boolean isStatic) { - if (context == Void.TYPE) { - return null; // Java methods cannot be invoked on null, or defined on Void - } - - final MethodSignature sig = getMethodSignature(opname, argType, isStatic); - Method ret = findCachedMethod(context, sig); - if (ret != null || hasCachedMethod(context, sig)) { - return ret; - } - + private static Method findNativeMethodInternal(final Class<?> context, final String opname, final Class<?> argType, + final boolean isStatic, final MethodSignature sig) { + Method ret = null; + final Method[] methods = context.getDeclaredMethods(); METHODS: for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if ((Modifier.isStatic(method.getModifiers()) == isStatic) && method.getName().equals(opname)) { Class<?>[] pts = method.getParameterTypes(); if (pts.length == 1) { - Class<?> pt = pts[0]; - if (argType == EnumLiteral.class && Enumerator.class.isAssignableFrom(pt)) { - ret = method; - break METHODS; - } - boolean ok = true; - if (!pt.isAssignableFrom(argType)) { - if (pt == boolean.class) - ok = argType == Boolean.class; - else if (pt == int.class) - ok = argType == Integer.class; - else if (pt == char.class) - ok = argType == Character.class; - else if (pt == long.class) - ok = argType == Long.class; - else if (pt == float.class) - ok = argType == Float.class; - else if (pt == double.class) - ok = argType == Double.class; - else - ok = argType == Void.TYPE; // any type - } - if (ok) { + if (checkParameterType(argType, pts[0])) { ret = method; break METHODS; } } } } - + if ((ret == null) && !isStatic && (context.getSuperclass() != null)) { - ret = findNativeMethod(context.getSuperclass(), opname, argType, isStatic); + ret = findNativeMethodInternal(context.getSuperclass(), opname, argType, isStatic, sig); + } else { + METHOD_CACHE.put(sig, ret != null ? new WeakReference<Method>(ret) : NULL_METHOD_REFERENCE); } - - cacheMethod(context, sig, ret); - + return ret; } @@ -1550,22 +1606,13 @@ public final class EMFTVMUtil { * The method name * @param isStatic * Whether to look for a static method or not + * @param sig + * the method signature * @return the method if found, null otherwise - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> - * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> - * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> - * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - public static Method findNativeMethod(final Class<?> context, final String opname, final boolean isStatic) { - if (context == Void.TYPE) { - return null; // Java methods cannot be invoked on null, or defined on Void - } - - final MethodSignature sig = getMethodSignature(opname, isStatic); - Method ret = findCachedMethod(context, sig); - if (ret != null || hasCachedMethod(context, sig)) { - return ret; - } + private static Method findNativeMethodInternal(final Class<?> context, final String opname, final boolean isStatic, + final MethodSignature sig) { + Method ret = null; final Method[] methods = context.getDeclaredMethods(); METHODS: for (int i = 0; i < methods.length; i++) { @@ -1579,15 +1626,53 @@ public final class EMFTVMUtil { } if ((ret == null) && !isStatic && (context.getSuperclass() != null)) { - ret = findNativeMethod(context.getSuperclass(), opname, isStatic); + ret = findNativeMethodInternal(context.getSuperclass(), opname, isStatic, sig); + } else { + METHOD_CACHE.put(sig, ret != null ? new WeakReference<Method>(ret) : NULL_METHOD_REFERENCE); } - cacheMethod(context, sig, ret); - return ret; } /** + * Checks whether the parameter type is compatible with the argument type + * + * @param argType + * the invocation argument type + * @param pt + * the method parameter type + * @return <code>true</code> if the parameter type is compatible, + * <code>false</code> otherwise + */ + private static boolean checkParameterType(final Class<?> argType, final Class<?> pt) { + if (argType == EnumLiteral.class && Enumerator.class.isAssignableFrom(pt)) { + return true; + } + if (pt.isAssignableFrom(argType)) { + return true; + } + if (pt == boolean.class){ + return argType == Boolean.class; + } + if (pt == int.class) { + return argType == Integer.class; + } + if (pt == char.class) { + return argType == Character.class; + } + if (pt == long.class) { + return argType == Long.class; + } + if (pt == float.class) { + return argType == Float.class; + } + if (pt == double.class) { + return argType == Double.class; + } + return argType == Void.TYPE; // any type + } + + /** * Compares 0-parameter <code>op</code> to <code>method</code>. * * @param op @@ -1951,113 +2036,71 @@ public final class EMFTVMUtil { } /** - * Returns <code>true</code> if the method cache contains the given caller and signature. - * - * @param caller - * The class of the method - * @param signature - * The method signature - * @return <code>true</code> if the method cache contains the given caller and signature - */ - private static boolean hasCachedMethod(final Class<?> caller, final MethodSignature signature) { - synchronized (METHOD_CACHE) { - final Map<MethodSignature, Method> sigMap = METHOD_CACHE.get(caller); - return (sigMap != null) && sigMap.containsKey(signature); - } - } - - /** - * Find a method in the cache. - * - * @param caller - * The class of the method - * @param signature - * The method signature - * @return the method - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> - * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> - * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> - * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> - */ - private static Method findCachedMethod(final Class<?> caller, final MethodSignature signature) { - synchronized (METHOD_CACHE) { - final Map<MethodSignature, Method> sigMap = METHOD_CACHE.get(caller); - return (sigMap != null) ? sigMap.get(signature) : null; - } - } - - /** - * Stores a method in a cache. - * - * @param caller - * The class of the method - * @param signature - * The method signature - * @param method - * The method to store - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> - * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> - * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> - * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> - */ - private static void cacheMethod(final Class<?> caller, final MethodSignature signature, final Method method) { - synchronized (METHOD_CACHE) { - Map<MethodSignature, Method> sigMap = METHOD_CACHE.get(caller); - if (sigMap == null) { - sigMap = new HashMap<MethodSignature, Method>(); - METHOD_CACHE.put(caller, sigMap); - } - sigMap.put(signature, method); - } - } - - /** * Generates a signature to store methods. * + * @param context + * the method declaring class * @param name + * the method name * @param argumentTypes + * the argument types * @param isStatic + * whether the method is static * @return The method signature - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> + * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic + * Jouault</a> * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - private static MethodSignature getMethodSignature(final String name, final Class<?>[] argumentTypes, - final boolean isStatic) { - return new MethodSignature(name, argumentTypes, isStatic); + private static MethodSignature getMethodSignature(final Class<?> context, final String name, + final Class<?>[] argumentTypes, final boolean isStatic) { + return new MethodSignature(context, name, argumentTypes, isStatic); } /** * Generates a signature to store methods. * + * @param context + * the method declaring class * @param name + * the method name * @param argumentType + * the (single) argument type + * @param isStatic + * whether the method is static * @param isStatic * @return The method signature - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> + * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic + * Jouault</a> * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - private static MethodSignature getMethodSignature(final String name, final Class<?> argumentType, - final boolean isStatic) { - return new MethodSignature(name, new Class<?>[] { argumentType }, isStatic); + private static MethodSignature getMethodSignature(final Class<?> context, final String name, + final Class<?> argumentType, final boolean isStatic) { + return new MethodSignature(context, name, new Class<?>[] { argumentType }, isStatic); } /** * Generates a signature to store methods. * + * @param context + * the method declaring class * @param name + * the method name * @param isStatic + * whether the method is static * @return The method signature - * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic Jouault</a> + * @author <a href="mailto:frederic.jouault@univ-nantes.fr">Frederic + * Jouault</a> * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a> * @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a> */ - private static MethodSignature getMethodSignature(final String name, final boolean isStatic) { - return new MethodSignature(name, null, isStatic); + private static MethodSignature getMethodSignature(final Class<?> context, final String name, + final boolean isStatic) { + return new MethodSignature(context, name, null, isStatic); } /** @@ -2460,12 +2503,15 @@ public final class EMFTVMUtil { if (method == null) { return null; } - Method rootMethod = ROOT_METHOD_CACHE.get(method); + RootMethodCacheAccesses++; + final WeakReference<Method> rootMethodReference = ROOT_METHOD_CACHE.get(method); + Method rootMethod = rootMethodReference != null ? rootMethodReference.get() : null; if (rootMethod != null) { + RootMethodCacheHits++; return rootMethod; } rootMethod = findRootMethodInner(method); - ROOT_METHOD_CACHE.put(method, rootMethod); + ROOT_METHOD_CACHE.put(method, new WeakReference<Method>(rootMethod)); return rootMethod; } @@ -2521,4 +2567,24 @@ public final class EMFTVMUtil { return methodModifiers & (Modifier.PRIVATE + Modifier.PROTECTED + Modifier.PUBLIC + Modifier.STATIC); } + /** + * Returns the hit rate of the method cache. + * + * @return the hit rate of the method cache, or <code>-1.0</code> if no hits + * were recorded yet + */ + public static double getMethodCacheHitRate() { + return MethodCacheAccesses > 0 ? (double) MethodCacheHits / (double) MethodCacheAccesses : -1.0; + } + + /** + * Returns the hit rate of the root method cache. + * + * @return the hit rate of the root method cache, or <code>-1.0</code> if no + * hits were recorded yet + */ + public static double getRootMethodCacheHitRate() { + return RootMethodCacheAccesses > 0 ? (double) RootMethodCacheHits / (double) RootMethodCacheAccesses : -1.0; + } + } diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/MethodSignature.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/MethodSignature.java index 6c44da01..f150c0fb 100644 --- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/MethodSignature.java +++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/util/MethodSignature.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Dennis Wagelaar. + * Copyright (c) 2016-2017 Dennis Wagelaar. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,8 +21,9 @@ import java.util.Arrays; */ public final class MethodSignature { + private final String context; private final String name; - private final Class<?>[] argumentTypes; + private final String[] argumentTypes; private final boolean isStatic; /** @@ -35,14 +36,31 @@ public final class MethodSignature { * @param isStatic * whether the method is static */ - public MethodSignature(String name, Class<?>[] argumentTypes, boolean isStatic) { + public MethodSignature(Class<?> context, String name, Class<?>[] argumentTypes, boolean isStatic) { super(); + this.context = context.getName(); this.name = name; - this.argumentTypes = argumentTypes; + if (argumentTypes != null) { + this.argumentTypes = new String[argumentTypes.length]; + for (int i = 0; i < argumentTypes.length; i++) { + this.argumentTypes[i] = argumentTypes[i].getName(); + } + } else { + this.argumentTypes = null; + } this.isStatic = isStatic; } /** + * Returns the method context (i.e. declaring class). + * + * @return the context + */ + public String getContext() { + return context; + } + + /** * Returns the method name. * * @return the name @@ -56,7 +74,7 @@ public final class MethodSignature { * * @return the argumentTypes */ - public Class<?>[] getArgumentTypes() { + public String[] getArgumentTypes() { return argumentTypes; } @@ -76,9 +94,10 @@ public final class MethodSignature { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + Arrays.hashCode(argumentTypes); - result = prime * result + (isStatic ? 1231 : 1237); + result = prime * result + ((context == null) ? 0 : context.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + (isStatic ? 1231 : 1237); + result = prime * result + Arrays.hashCode(argumentTypes); return result; } @@ -94,15 +113,20 @@ public final class MethodSignature { if (getClass() != obj.getClass()) return false; MethodSignature other = (MethodSignature) obj; - if (!Arrays.equals(argumentTypes, other.argumentTypes)) - return false; - if (isStatic != other.isStatic) + if (context == null) { + if (other.context != null) + return false; + } else if (!context.equals(other.context)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; + if (isStatic != other.isStatic) + return false; + if (!Arrays.equals(argumentTypes, other.argumentTypes)) + return false; return true; } @@ -111,8 +135,8 @@ public final class MethodSignature { */ @Override public String toString() { - return "MethodSignature [name=" + name + ", argumentTypes=" + Arrays.toString(argumentTypes) + ", isStatic=" - + isStatic + "]"; + return "MethodSignature [context=" + context + ", name=" + name + ", argumentTypes=" + + Arrays.toString(argumentTypes) + ", isStatic=" + isStatic + "]"; } } |