 <p>Answer can be found in the documentation for Proxy class: <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html" rel="nofollow">https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html</a></p> <blockquote> <p>An invocation of the hashCode, equals, or toString methods declared in java.lang.Object on a proxy instance will be encoded and dispatched to the invocation handler's invoke method in the same manner as interface method invocations are encoded and dispatched, as described above. The declaring class of the Method object passed to invoke will be java.lang.Object. Other public methods of a proxy instance inherited from java.lang.Object are not overridden by a proxy class, so invocations of those methods behave like they do for instances of java.lang.Object.</p> </blockquote> <p>Also, I think it has something to do with the fact that the <code>toString()</code> method has a default definition:</p> <pre><code>public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } </code></pre> <p>While <code>getClass()</code> (and <code>wait()</code>, <code>notify()</code> etc.) are defined as:</p> <pre><code>public final native Class&lt;?&gt; getClass(); </code></pre> <p>So, to differentiate between which methods will not be proxied you can look fo presence of <code>final native</code> in the method definition.</p>