我有两个可运行的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);
}