首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >[Java]关于动态加载及卸载jar后的一些思考

[Java]关于动态加载及卸载jar后的一些思考

作者头像
master336
发布2026-06-15 19:29:35
发布2026-06-15 19:29:35
550
举报

实现

编写要加载/卸载的测试jar

代码语言:javascript
复制
package cn.com.test;

public class JarTest {
    static {
        System.out.println("I am JarTest's static code");
    }
    public static void run(){
        System.out.println("I am JarTest's static method");
    }
    public void run1(){
        System.out.println("I am JarTest's  method>>>"+this);
    }
}

将以上class 打包成jartest.jar 假定打包文件位置放在/Users/tmp/jartest.jar

使用jar -cvf jartest.jar **path 打包或者使用IDE打包都行

编写加载/卸载测试工具

代码语言:javascript
复制
package jar;

import sun.misc.ClassLoaderUtil;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class LoadJar {
    static Object jarTestInstance = null;
    static ClassLoader myClassLoader1;
    static Class<?> jarTest;

    public static void main(String[] args) throws MalformedURLException, InterruptedException {
        System.out.println("befor laod jar");
        loadClassAndRun();
        Thread.sleep(1000);
        System.out.println("laod jar");
        loadJar();
        Thread.sleep(1000);
        System.out.println("after load jar");
        loadClassAndRun();
        Thread.sleep(1000);
        System.out.println("start unload jar");
        unLoad();
        Thread.sleep(1000);
        System.out.println("after unload jar");
        loadClassAndRun();
        System.out.println("laod jar");
        loadJar();
        Thread.sleep(1000);
        System.out.println("after load jar");
        loadClassAndRun();
    }

    private static void loadClassAndRun() {
        if(myClassLoader1 == null) {
            myClassLoader1 = LoadJar.class.getClassLoader();
        }
        try {
            jarTest = myClassLoader1.loadClass("cn.com.test.JarTest");
            jarTestInstance = jarTest.newInstance();
            for (Method method : jarTest.getMethods()) {
                try {
                    method.invoke(jarTestInstance);
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void loadJar() throws MalformedURLException {
        URL url = new File("/Users/tmp/jartest.jar").toURI().toURL();
        myClassLoader1 = new URLClassLoader(new URL[] { url});
    }

    // 卸载jar包的代码如下:
    public static void unLoad() {

        if (null != myClassLoader1 && myClassLoader1 instanceof URLClassLoader) {
            System.out.println("unload URLClassLoader ");
            URLClassLoader loader = (URLClassLoader) myClassLoader1;
            try {
            	// 关注下这里,这里一会儿要改
                ClassLoaderUtil.releaseLoader(loader);
                loader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

执行结果

在这里插入图片描述
在这里插入图片描述

思考

URLClassLoader.close()释放掉资源后,刚加载过的class仍然可以继续使用? 官方解释:

在这里插入图片描述
在这里插入图片描述

*** 从官方的解释中来看,确实如此 *** 那么在什么时候会被回收呢? 反思类的加载机制,类在没有引用时可被GC,改动unLoad() 方法如下:

代码语言:javascript
复制
    // 卸载jar包的代码如下:
    public static void unLoad() {

        if (null != myClassLoader1 && myClassLoader1 instanceof URLClassLoader) {
            System.out.println("unload URLClassLoader ");
            URLClassLoader loader = (URLClassLoader) myClassLoader1;
            try {
                jarTest = null;
                jarTestInstance = null;
                myClassLoader1 = null;
                System.gc();
                Thread.sleep(2000);
                ClassLoaderUtil.releaseLoader(loader);
                loader.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

再次测试:

在这里插入图片描述
在这里插入图片描述

需要注意的是GC不是立即执行的,可能你的验证结果跟我不一样,注意区分!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现
  • 执行结果
  • 思考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档