热加载卸载jar包
热加载卸载jar包
2020-12-29
1 类层次
2 源代码
hot-load-unload-jar项目
PluginClassLoader.java内容如下:
package com.test; import java.net.JarURLConnection; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; /** * 插件类加载器,在插件目录中搜索jar包,并为发现的资源(jar)构造一个类加载器,将对应的jar添加到classpath中 * @author strawxdl */ public class PluginClassLoader extends URLClassLoader { private List<JarURLConnection> cachedJarFiles = new ArrayList<JarURLConnection>(); public PluginClassLoader() { super(new URL[] {}, findParentClassLoader()); } /** * 将指定的文件url添加到类加载器的classpath中去,并缓存jar connection,方便以后卸载jar * @param 一个可想类加载器的classpath中添加的文件url */ public void addURLFile(URL file) { try { // 打开并缓存文件url连接 URLConnection uc = file.openConnection(); if (uc instanceof JarURLConnection) { uc.setUseCaches(true); ((JarURLConnection) uc).getManifest(); cachedJarFiles.add((JarURLConnection)uc); } } catch (Exception e) { System.err.println("Failed to cache plugin JAR file: " + file.toExternalForm()); } addURL(file); } /** * 卸载jar包 */ public void unloadJarFiles() { for (JarURLConnection url : cachedJarFiles) { try { System.err.println("Unloading plugin JAR file " + url.getJarFile().getName()); url.getJarFile().close(); url=null; } catch (Exception e) { System.err.println("Failed to unload JAR file\n"+e); } } } /** * 定位基于当前上下文的父类加载器 * @return 返回可用的父类加载器. */ private static ClassLoader findParentClassLoader() { ClassLoader parent = PluginManager.class.getClassLoader(); if (parent == null) { parent = PluginClassLoader.class.getClassLoader(); } if (parent == null) { parent = ClassLoader.getSystemClassLoader(); } return parent; } }
PluginManager.java内容如下:
package com.test; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * jar包 热加载/卸载 的初步实现 * https://www.cnblogs.com/xiaodl/p/plugin_hot_load.html */ public class PluginManager { static{ System.out.println(PluginManager.class.getName()); } private Map<String ,PluginClassLoader> pluginMap = new HashMap<String,PluginClassLoader>(); private static String packagename = "com.test.Plugin1"; public PluginManager(){ } public void doSome(String pluginName){ try{ Class<?> forName = Class.forName(packagename, true, getLoader(pluginName));//this.pluginMap.get(pluginName).loadClass(packagename); Plugin ins = (Plugin)forName.newInstance(); ins.doSome(); }catch(Exception e){ e.printStackTrace(); } } private void addLoader(String pluginName,PluginClassLoader loader){ this.pluginMap.put(pluginName, loader); } private PluginClassLoader getLoader(String pluginName){ return this.pluginMap.get(pluginName); } public void loadPlugin(String pluginName){ this.pluginMap.remove(pluginName); PluginClassLoader loader = new PluginClassLoader(); String pluginurl = "jar:file:/D:/code/plugindemo/target/"+pluginName+".jar!/"; URL url = null; try { url = new URL(pluginurl); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } loader.addURLFile(url); addLoader(pluginName, loader); System.out.println("load " + pluginName + " success"); } public void unloadPlugin(String pluginName){ this.pluginMap.get(pluginName).unloadJarFiles(); this.pluginMap.remove(pluginName); } }
TestMain.java内容如下:
package com.test; import java.io.BufferedReader; import java.io.InputStreamReader; public class TestMain { public static void main(String[] args) throws Exception { PluginManager manager = new PluginManager();; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String cmd = br.readLine(); while(!cmd.equals("bye")){ if(cmd.startsWith("do")){ String pluginName = cmd.split(" ")[1]; manager.doSome(pluginName); } if(cmd.startsWith("load")){ String pluginName = cmd.split(" ")[1]; manager.loadPlugin(pluginName); } if(cmd.startsWith("unload")){ String pluginName = cmd.split(" ")[1]; manager.unloadPlugin(pluginName); } cmd = br.readLine(); } } }
plugin-contract项目
Plugin.java
package com.test; public interface Plugin { public void doSome(); }
plugin-demo项目
Plugin1.java内容如下:
package com.test; public class Plugin1 implements Plugin{ public void doSome(){ System.out.println("Plugin1 doSome ... is I? YES."); } }
备注:
打包成 plugin-demo-1.0-SNAPSHOT.jar
Plugin1.java 内容1: System.out.println("Plugin1 doSome ... is I? YES."); 内容2: System.out.println("Plugin1 doSome ... is I? No.");
3 执行演示