热加载卸载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;
    }
}
View Code

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);
    }
}
View Code

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();
        }
    }
}
View Code

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 执行演示

 

 

 

 

参考:

[1]  jar包 热加载/卸载 的初步实现 

posted @ 2020-12-30 12:01  明-Ming  阅读(793)  评论(0编辑  收藏  举报