加载的JAR不会在关闭时释放所有资源

时间:2014-07-07 13:22:35

标签: java multithreading jar

我有两个可运行的JAR文件。主JAR运行主应用程序,辅助JAR是应用程序的插件。

我在主应用程序中使用JarClassLoader(由Oracle located here定义)来加载插件,并向main方法发送一个参数(关闭或启动)。

一旦插件关闭,我希望能够删除JAR文件或用其他东西替换它。但是,即使关闭所有插件线程,在类加载器上调用.close()方法,并且对类加载器的所有引用都设置为null,插件的JAR仍然由java使用并由Windows锁定。

如何删除此文件上的锁定?

primaryjar / MainApp.java

public class MainApp
{
  static PluginHandler ph;
  public static void main(String[] args) 
  {
    ph = new PluginHandler(System.getProperty("user.dir"));
    ph.startupPlugin();
    Thread.sleep(20000);
    ph.shutdownPlugin();
    Thread.sleep(20000);
    ph.startupPlugin();
  }
}

primaryjar / PluginHandler.java

public class PluginHandler
{
  private static JarClassLoader jcl = null;
  private String dir;

  public PluginHandler(String dir)
  { this.dir = dir;  
  }

  public void startupPlugin()
  {
    try 
    {
      jcl = JarClassLoader.generateFromString(dir + "plugin.jar");
      String name = jcl.getMainClassName();
      String[] newArgs = { "-startup" };
      jcl.invokeClass(name, newArgs);
    }
    catch (Exception e)
    {
    }
  }

  public void shutdownPlugin()
  {
    try 
    {
      jcl = JarClassLoader.generateFromString(dir + "plugin.jar");
      String name = jcl.getMainClassName();
      String[] newArgs = { "-shutdown" };
      jcl.invokeClass(name, newArgs);
      jcl.close();
      jcl = null;
    }
    catch (Exception e)
    {
    }
  }
}

pluginsjar / PluginMain.java

public class PluginMain {
    static ScheduledThreadPoolExecutor ste; 

    public static void main(String[] args) throws Exception
    {
      //startup arg
      if(args[0].equals("-startup"))
      {
          ste = new ScheduledThreadPoolExecutor(3);
          Task t1 = new Task("Hello");
          Task t2 = new Task("Salutations");
          Task t3 = new Task("Stuff");
          ste.scheduleWithFixedDelay(t1, 0, 5, TimeUnit.SECONDS);
          ste.scheduleWithFixedDelay(t2, 0, 5, TimeUnit.SECONDS);
          ste.scheduleWithFixedDelay(t3, 0, 5, TimeUnit.SECONDS);
      }

      else if (args[0].equals("-shutdown"))
      {
          ste.shutdown();
          ste.awaitTermination(10000, TimeUnit.SECONDS);
      }
    }
}

class Task implements Runnable
{
    String word; 
    int invoke = 0;
    public Task(String word)
    {
        this.word = word;
    }
    public void run() {
        invoke++;
        System.out.println("Words " + invoke + ": " + word);
    }
}

找到另一个主题,我在here进行了一些研究和玩弄,但无法找到可行的解决方案。

编辑:我添加了一个方便的方法来创建一个JarClassLoader,就像它在“JarRunner”中所做的一样。我在上面链接的JarClassLoader文档的类。

public static JarClassLoader generateFromString(String path) 
            throws MalformedURLException
    {
      File pluginDir = new File(path);
      URL loadPath = pluginDir.toURI().toURL();
      return new JarClassLoader(loadPath);
    }

0 个答案:

没有答案