gpt4 book ai didi

Java ClassLoader 不断创建更多线程

转载 作者:搜寻专家 更新时间:2023-11-01 03:37:56 25 4
gpt4 key购买 nike

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

  1. 通过 URLClassLoader 加载 .class 文件并开始执行 main 方法。
  2. main 方法生成另一个线程 (VIA ScheduledThreadPoolExecutor),它会定期查询服务。
  3. 生成一个新线程来处理清理:
    1. ScheduledThreadPoolExecutor 上调用 .shutdown(),然后所有线程都终止。
    2. URLClassLoader 上调用 .close() 并将 URLClassLoader 变量设置为 null。
  4. 然后清理线程 hibernate 以允许手动替换 .class 文件。
  5. 清理线程然后重新启动进程,加载新的 .class 文件并运行它们。

这些步骤中的一切都正常,新的 .class 文件按预期工作。

当插件再次启动时,我遇到的问题就开始了。每次运行重启过程时,它都会生成一个额外的插件实例。

第一次运行:1 个正在运行的插件
第二次运行:2 个正在运行的插件
第三次运行:3 个正在运行的插件
等等

我觉得奇怪的是,它并没有在每次启动时产生两倍数量的插件,它只会产生一个额外的插件。额外的代码只能再执行一次,而不是由每个先前的线程执行。每次后续调用 startup() 时,它会创建一个新的 URLClassLoader(旧的已关闭并清空),是否也启动所有过去的 URLClassLoaders 不知何故?尝试在 Debug模式下运行它,但它没有跟踪每个 Activity 线程。我需要维护以前的 URLClassLoader,如果没有它,对在后台运行的现有对象的任何引用都将被删除。

鉴于程序的复杂性,很难给 SSCCE。

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
}
}

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

最佳答案

Mark W 的建议让我陷入困境,使用 jmap 和其他过程分析程序来查明究竟发生了什么。那里有大量有用的实用程序。结合 VisualVMEclipse Memory Analyzer (MAT) 我发现我没有关闭日志的 FileHandler。浪费了这么多时间!

关于Java ClassLoader 不断创建更多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24806458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com