我的程序的整体概念包括从.class文件加载插件,运行它,关闭它,手动更新.class文件,最后重新打开它。目前它
URLClassLoader
加载.class文件并开始执行main方法。 ScheduledThreadPoolExecutor
),每个线程定期查询服务。 .shutdown()
上调用ScheduledThreadPoolExecutor
,所有线程都会死亡。 .close()
上调用URLClassLoader
并将URLClassLoader
变量设置为null。 这些步骤中的所有内容都有效,新的.class文件按预期工作。
当插件再次启动时,我遇到的问题就开始了。每次运行重启过程时,它都会产生一个额外的插件实例。
第一次运行:1个正在运行的插件
第二轮:2个运行插件
第3次运行:3个运行插件
等等
我觉得奇怪的是,它并没有在每次启动时产生两倍的插件数量,它只会产生一个额外的插件。额外的代码只能再执行一次,而不是每个先前的线程。每次后续的第二次调用startup()
是否会创建一个新的URLClassLoader
(旧的URLClassLoaders
,而旧的URLClassLoader
也会以某种方式启动所有过去的public class PluginHandler
{
private static URLClassLoader cl = null;
private static String = "somedir";
public void restart()
{
(new Thread() {
public void run() {
if (cl != null) {
cl.invokeClass(pckg, "main", "-shutdown");
cl.close();
cl = null;
}
try {
Thread.sleep(15000);
} (catch InterruptedException e) {
System.out.println("Interrupted");
}
cl = URLClassLoader cl = new URLClassLoader(new URL[] { new File(path).toURI().toURL() } ));
cl.invokeClass(pckg, "main", "-startup");
}).start();
}
public URLClassLoader invokeClass(String pckgName, String mthdName, String[] args)
throws Exception
{
Class<?> loadedClass = cl.loadClass(pckgName);
Method m = loadedClass.getMethod(mthdName, args.getClass());
m.invoke(null, new Object[] { args });
return urlcl;
}
}
public class PluginMain
{
public static void main(String[] args) {
if (args[0].equals("-startup") {
new PluginController.run();
}
else if (args[0].equals("-shutdown") {
PluginController.shutdown();
}
}
}
public class PluginController implements Runnable
{
static ScheduledThreadPoolExecutor st;
static ScheduledFuture<?> sf;
public void run() {
st = new Scheduled ThreadPoolExecutor(1);
sf = st.scheduleWithFixedDelay(new Plugin(), 0, 10, Time_Unit.SECONDS);
sf.wait();
System.out.println("Returns from run()"); //prints after shutdown is run.
}
public static void shutdown() {
sf.cancel();
st.shutdown();
}
}
public class Plugin implements Runnable
{
public void run() {
//Queries some service
}
}
?尝试在调试模式下运行它,并且它不跟踪每个活动线程。我需要维护之前的{{1}},如果没有它,则删除对后台运行的现有对象的任何引用。
鉴于该计划的复杂性,很难给予SSCCE。
{{1}}
编辑:所有插件同时运行相同的代码行。我提到了那些睡眠,我怀疑它会使不同的线程完全同步。
答案 0 :(得分:1)
Mark W的建议引导我使用jmap和其他过程分析程序来查明究竟发生了什么。那里有很多有用的工具。通过VisualVM和Eclipse Memory Analyzer (MAT) 的组合,我能够发现我没有为我的日志关闭FileHandler。耗费了这么多小时!