16

I am seeing following exception when I try to use dynamic proxy

 com.intellij.rt.execution.application.AppMain DynamicProxy.DynamicProxy
Exception in thread "main" java.lang.IllegalArgumentException: interface Interfaces.IPerson is not visible from class loader
    at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
    at DynamicProxy.Creator.getProxy(Creator.java:18)
    at DynamicProxy.DynamicProxy.main(DynamicProxy.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Any idea what I need to do to resolve it

3 Answers 3

12

If this is web application, then you should use the web application classloader when creating dynamic proxy. So, for example instead of:

Proxy.newProxyInstance(
  ClassLoader.getSystemClassLoader(),
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
    // (...)
});

try:

Proxy.newProxyInstance(
  this.getClass().getClassLoader(), // here is the trick
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
    // (...)
});

For instance, hierarchy of tomcat class loaders (other web containers have similar) is following:

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ... 

And it is the webapp classloader which contains classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application.

Sign up to request clarification or add additional context in comments.

Comments

6

When your DynamicProxy tries to do Class.forName(youInterfaceClass.getName()) the resulting java.lang.Class instance is different from the one you passed when you created the proxy. In other words you have two class objects with the same name and the proxy is not sure which one is the right one (doesn't matter whether they are the same).

Usually, this happens when the interface you are trying to proxy is in a library loaded through two different classloaders (i.e. Tomcat's 'common' and 'application').

If this doesn't help, please post more info on your application - especially if you are using any application server, Spring or OSGi.

Comments

0

I had the same problem using spring boot, I solve it injecting ResourceLoader, getting its class loader.

@Autowired
private ResourceLoader resourceLoader;

....
ClassLoader classLoader = resourceLoader.getClassLoader();
...


Proxy.newProxyInstance(
  classLoader, //for example...
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
  // (...)
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.