0

I have a problem with the "JavaClassLoader" library. I want to program a launcher for a application. At the end it should be possible to shutdown the program, to update and to start again. Now, I always get an NoSuchMethodEx when I try to invoke methods with arguments.

The main class that I want to start, implemented following (part of apache Daemon):

package org.apache.commons.daemon;
public interface Daemon {
    public void init(DaemonContext context) throws DaemonInitException, Exception;
    public void start() throws Exception;
    public void stop() throws Exception;
    public void destroy();
}

In my Launcher following happens:

// set cglib proxy
ProxyProviderFactory.setDefaultProxyProvider(new CglibProxyProvider());
// load instance
JarClassLoader jcl = new JarClassLoader();
jcl.add("application.jar");
JclObjectFactory factory = JclObjectFactory.getInstance(true);
this.application = (Daemon) factory.create(jcl, "de.FabiUnne.Application");

Now if I try to invoke a method with no argument (e.g. #start()), everything works. I get an error when I try to invoke the #init(DaemonContext) method.

The stacktrace:

Exception in thread "main" java.lang.NoSuchMethodException: de.FabiUnne.Application.init(org.apache.commons.daemon.DaemonContext)
  at java.lang.Class.getMethod(Class.java:1670)
  at org.xeustechnologies.jcl.proxy.CglibProxyProvider$CglibProxyHandler.intercept(CglibProxyProvider.java:52)
  at org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.init(<generated>)
  and 2 more...

The funny thing is that the method is indeed present in any case.

<- this.application.getClass().getMethods()
-> [ ...
public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.init(org.apache.commons.daemon.DaemonContext) throws org.apache.commons.daemon.DaemonInitException,java.lang.Exception, 
public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.start() throws java.lang.Exception, 
public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.destroy(), 
public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.stop() throws java.lang.Exception, 
... ]

Why can not I call the #init() method anyway?

2 Answers2

1

I'm not familiar with the framework you're using. But if I got it right than the new Class loader you create is the reason of the exception. If you would obtain the Instance of the DaemonContext from your jcl you should be able to invoke the method. You could also create the new Class loader as child of the application class loader. The way it currently is there are two different classes of type DaemonContext one from each distinct class loader.

Christian Frommeyer
  • 1,390
  • 1
  • 12
  • 20
  • Do you think that creating a new Thread with context class loader `jcl` could load the correct class `DaemonContext`? – CoronA May 26 '15 at 05:40
  • Ok, I read through the Jcl doku... This actually should work as far as I can see. Please provide the code you use to actually invoke init(...). – Christian Frommeyer May 26 '15 at 09:05
0

jcl: manipulating-class-loading-order

@ChristianFrommeyer gave me the solution. I want to explain it, so it's own answer.

The launcher is still loaded by the "normal" class loader. All objects that are loaded in this class will be loaded by the same class loader as the Launcher. I load now from the other ClasLoader of (github.com/kamranzafar/JCL). The class that's stored in the application as dependency is loaded on the second loader. This class is different, as the above loaded.

public final void org.apache.commons.daemon.Daemon.init( ... ), 

are not the same as

public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.init( ... ), 

So I tell the JCL, that he should not override loaded objects. Here, the following Loader achieve the same effect.

jcl.getCurrentLoader().setOrder(1); // or
jcl.getParentLoader().setOrder(1); // or
jcl.getSystemLoader().setOrder(1);

The objects that are present in both classloaders, are now identical, because they both come from the local Loader.