Java ClassLoader不断创建更多线程

时间:2014-07-17 14:35:17

标签: java multithreading

我的程序的整体概念包括从.class文件加载插件,运行它,关闭它,手动更新.class文件,最后重新打开它。目前它

  1. 通过URLClassLoader加载.class文件并开始执行main方法。
  2. 主要方法产生另一个线程(VIA ScheduledThreadPoolExecutor),每个线程定期查询服务。
  3. 产生一个新线程来处理清理:
    1. .shutdown()上调用ScheduledThreadPoolExecutor,所有线程都会死亡。
    2. .close()上调用URLClassLoader并将URLClassLoader变量设置为null。
  4. 然后清理线程休眠以允许手动替换.class文件。
  5. 清理线程然后重新开始处理,加载新的.class文件并运行它们。
  6. 这些步骤中的所有内容都有效,新的.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}}

    编辑:所有插件同时运行相同的代码行。我提到了那些睡眠,我怀疑它会使不同的线程完全同步。

1 个答案:

答案 0 :(得分:1)

Mark W的建议引导我使用jmap和其他过程分析程序来查明究竟发生了什么。那里有很多有用的工具。通过VisualVMEclipse Memory Analyzer (MAT) 的组合,我能够发现我没有为我的日志关闭FileHandler。耗费了这么多小时!