我遇到了" JavaClassLoader"图书馆。我想为应用程序编写一个启动程序。最后应该可以关闭程序,更新并重新开始。 现在,当我尝试使用参数调用方法时,我总是得到一个NoSuchMethodEx。
我想要启动的主类,实现如下(apache守护进程的一部分):
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();
}
在我的启动器中发生以下情况:
// 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");
现在,如果我尝试调用没有参数的方法(例如#start()),一切正常。当我尝试调用#init(DaemonContext)方法时出现错误。
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...
有趣的是,无论如何,这种方法确实存在。
<- 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,
... ]
为什么我不能调用#init()方法呢?
答案 0 :(得分:1)
我不熟悉你正在使用的框架。但是,如果我得到它,那么你创建的新类加载器就是异常的原因。如果您从jcl获取DaemonContext的实例,您应该能够调用该方法。您还可以将新的类加载器创建为应用程序类加载器的子级。目前的方式是每个不同的类加载器都有两个不同类型的DaemonContext。
答案 1 :(得分:0)
jcl: manipulating-class-loading-order
@ChristianFrommeyer给了我解决方案。我想解释一下,所以这是答案。
启动器仍由“普通”类加载器加载。此类中加载的所有对象都将由与Launcher相同的类加载器加载。 我现在从(github.com/kamranzafar/JCL)的其他ClasLoader加载。作为依赖项存储在应用程序中的类将加载到第二个加载器上。这个类是不同的,如上所述。
public final void org.apache.commons.daemon.Daemon.init( ... ),
与
不同public final void org.apache.commons.daemon.Daemon$$EnhancerByCGLIB$$b9db6482.init( ... ),
所以我告诉JCL,他不应该覆盖加载的对象。这里,以下Loader实现了同样的效果。
jcl.getCurrentLoader().setOrder(1); // or
jcl.getParentLoader().setOrder(1); // or
jcl.getSystemLoader().setOrder(1);
两个类加载器中存在的对象现在都是相同的,因为它们都来自本地Loader。