Fix issue 643 using a slightly modified version of the patch provided by
Stuart.
diff --git a/core/src/com/google/inject/internal/ProxyFactory.java b/core/src/com/google/inject/internal/ProxyFactory.java
index 3ab04bd..0b39f76 100644
--- a/core/src/com/google/inject/internal/ProxyFactory.java
+++ b/core/src/com/google/inject/internal/ProxyFactory.java
@@ -24,6 +24,7 @@
 import com.google.common.collect.Maps;
 import com.google.inject.spi.InjectionPoint;
 
+import net.sf.cglib.core.MethodWrapper;
 import net.sf.cglib.proxy.Callback;
 import net.sf.cglib.proxy.CallbackFilter;
 import net.sf.cglib.proxy.Enhancer;
@@ -169,7 +170,7 @@
     // to this injector. Otherwise, the proxies for each injector will waste PermGen memory
     try {
     Enhancer enhancer = BytecodeGen.newEnhancer(declaringClass, visibility);
-    enhancer.setCallbackFilter(new IndicesCallbackFilter(declaringClass, methods));
+    enhancer.setCallbackFilter(new IndicesCallbackFilter(methods));
     enhancer.setCallbackTypes(callbackTypes);
     return new ProxyConstructor<T>(enhancer, injectionPoint, callbacks, interceptors);
     } catch (Throwable e) {
@@ -198,35 +199,35 @@
   }
 
   /**
-   * A callback filter that maps methods to unique IDs. We define equals and hashCode using the
-   * declaring class so that enhanced classes can be shared between injectors.
+   * A callback filter that maps methods to unique IDs. We define equals and
+   * hashCode without using any state related to the injector so that enhanced
+   * classes intercepting the same methods can be shared between injectors (and
+   * child injectors, etc).
    */
   private static class IndicesCallbackFilter implements CallbackFilter {
-    final Class<?> declaringClass;
-    final Map<Method, Integer> indices;
+    final Map<Object, Integer> indices;
+    final int hashCode;
 
-    IndicesCallbackFilter(Class<?> declaringClass, List<Method> methods) {
-      this.declaringClass = declaringClass;
-      final Map<Method, Integer> indices = Maps.newHashMap();
+    IndicesCallbackFilter(List<Method> methods) {
+      final Map<Object, Integer> indices = Maps.newHashMap();
       for (int i = 0; i < methods.size(); i++) {
-        Method method = methods.get(i);
-        indices.put(method, i);
+        indices.put(MethodWrapper.create(methods.get(i)), i);
       }
-
       this.indices = indices;
+      this.hashCode = indices.hashCode();
     }
 
     public int accept(Method method) {
-      return indices.get(method);
+      return indices.get(MethodWrapper.create(method));
     }
 
     @Override public boolean equals(Object o) {
       return o instanceof IndicesCallbackFilter &&
-          ((IndicesCallbackFilter) o).declaringClass == declaringClass;
+          ((IndicesCallbackFilter) o).indices.equals(indices);
     }
 
     @Override public int hashCode() {
-      return declaringClass.hashCode();
+      return hashCode;
     }
   }
 
diff --git a/core/test/com/google/inject/MethodInterceptionTest.java b/core/test/com/google/inject/MethodInterceptionTest.java
index 6d6d596..6fe8b4e 100644
--- a/core/test/com/google/inject/MethodInterceptionTest.java
+++ b/core/test/com/google/inject/MethodInterceptionTest.java
@@ -79,7 +79,7 @@
 
     Interceptable nullFoosOne = childOne.getInstance(Interceptable.class);
     assertNotNull(nullFoosOne.bar());
-    assertNull(nullFoosOne.foo());
+    assertNull(nullFoosOne.foo()); // confirm it's being intercepted
 
     Injector childTwo = injector.createChildInjector(new AbstractModule() {
       protected void configure() {
@@ -88,10 +88,21 @@
     });
 
     Interceptable nullFoosTwo = childTwo.getInstance(Interceptable.class);
-    assertNull(nullFoosTwo.foo());
+    assertNull(nullFoosTwo.foo()); // confirm it's being intercepted
 
     assertSame("Child injectors should share proxy classes, otherwise memory leaks!",
         nullFoosOne.getClass(), nullFoosTwo.getClass());
+    
+    Injector injector2 = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(Matchers.any(), Matchers.returns(only(Foo.class)),
+            new ReturnNullInterceptor());
+      }
+    });
+    Interceptable separateNullFoos = injector2.getInstance(Interceptable.class);
+    assertNull(separateNullFoos.foo()); // confirm it's being intercepted
+    assertSame("different injectors should share proxy classes, otherwise memory leaks!",
+        nullFoosOne.getClass(), separateNullFoos.getClass());
   }
 
   public void testGetThis() {