@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Class declaringClass = method.getDeclaringClass();

		if (declaringClass == Object.class) {
			if (method.equals(hashCodeMethod)) {
				return proxyHashCode(proxy);
			} else if (method.equals(equalsMethod)) {
				return proxyEquals(proxy, args[0]);
			} else if (method.equals(toStringMethod)) {
				return proxyToString(proxy);
			} else {
				throw new InternalError("unexpected Object method dispatched: "
						+ method);
			}
		} else {
			for (int i = 0; i < interfaces.length; i++) {
				if (declaringClass.isAssignableFrom(interfaces[i])) {
					try {
						return method.invoke(delegates[i], args);
					} catch (InvocationTargetException e) {
						throw e.getTargetException();
					}
				}
			}

			return invokeNotDelegated(proxy, method, args);
		}
	}