java type_error ai_generated true

java.lang.ClassCastException: class com.sun.proxy.$Proxy0 cannot be cast to class com.example.MyInterface (com.sun.proxy.$Proxy0 is in module java.base of loader 'app'; com.example.MyInterface is in unnamed module of loader 'app')

ID: java/classcastexception-proxy-invocationhandler

Also available as: JSON · Markdown · 中文
80%Fix Rate
85%Confidence
1Evidence
2023-11-20First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Java 8 active
Java 11 active
Java 17 active
Spring Framework 5.3.x active
Spring Framework 6.x active

Root Cause

This error occurs when a JDK dynamic proxy (Proxy.newProxyInstance) is created for an interface that is not visible to the proxy's class loader, typically because the interface is loaded by a different class loader or the proxy class is from a different module.

generic

中文

当为代理的类加载器不可见的接口创建JDK动态代理(Proxy.newProxyInstance)时发生,通常因为接口由不同的类加载器加载或代理类来自不同模块。

Official Documentation

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Proxy.html

Workarounds

  1. 85% success Ensure the interface is loaded by the same class loader as the proxy: `ClassLoader commonLoader = Thread.currentThread().getContextClassLoader(); MyInterface proxy = (MyInterface) Proxy.newProxyInstance(commonLoader, new Class[]{MyInterface.class}, handler);`
    Ensure the interface is loaded by the same class loader as the proxy: `ClassLoader commonLoader = Thread.currentThread().getContextClassLoader(); MyInterface proxy = (MyInterface) Proxy.newProxyInstance(commonLoader, new Class[]{MyInterface.class}, handler);`
  2. 90% success For Spring applications, configure proxy-target-class="true" to use CGLIB proxies instead of JDK dynamic proxies: `<aop:aspectj-autoproxy proxy-target-class="true"/>` or `@EnableAspectJAutoProxy(proxyTargetClass = true)`.
    For Spring applications, configure proxy-target-class="true" to use CGLIB proxies instead of JDK dynamic proxies: `<aop:aspectj-autoproxy proxy-target-class="true"/>` or `@EnableAspectJAutoProxy(proxyTargetClass = true)`.
  3. 80% success Move the interface definition to a shared library jar that is loaded by the common class loader (e.g., the bootstrap or extension class loader) to avoid class loader isolation.
    Move the interface definition to a shared library jar that is loaded by the common class loader (e.g., the bootstrap or extension class loader) to avoid class loader isolation.

中文步骤

  1. Ensure the interface is loaded by the same class loader as the proxy: `ClassLoader commonLoader = Thread.currentThread().getContextClassLoader(); MyInterface proxy = (MyInterface) Proxy.newProxyInstance(commonLoader, new Class[]{MyInterface.class}, handler);`
  2. For Spring applications, configure proxy-target-class="true" to use CGLIB proxies instead of JDK dynamic proxies: `<aop:aspectj-autoproxy proxy-target-class="true"/>` or `@EnableAspectJAutoProxy(proxyTargetClass = true)`.
  3. Move the interface definition to a shared library jar that is loaded by the common class loader (e.g., the bootstrap or extension class loader) to avoid class loader isolation.

Dead Ends

Common approaches that don't work:

  1. Casting the proxy to the concrete class instead of the interface 95% fail

    JDK dynamic proxies only implement interfaces, not concrete classes; casting to a concrete class will always fail.

  2. Adding the interface to the classpath multiple times in different jars 70% fail

    Multiple class loaders loading the same interface cause type identity issues; the proxy implements one version, but the cast expects another.

  3. Using CGLIB proxies instead without changing the interface visibility 60% fail

    CGLIB creates subclass proxies, which also require the target class to be accessible; the root cause (class loader mismatch) remains.