`
weifly
  • 浏览: 238791 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关闭URLClassLoader打开的jar包

阅读更多

URLClassLoader可以让开发者定义classloader,从jar文件或目录加载类文件。当URLClassloader引用的是一个jar文件时,用户是不能自己关闭这个被打开的jar文件的,有时候这真是一个大问题。tomcat中可以动态的删除一个web应用,那他是怎么关闭打开的jar文件呢?这个web应用可以有自己的jar包,tomcat的也必须要打开这些jar包的。

tomcat的webClassLoader自己来管理这些被打开的jar文件,并在classloader中提供了closeJars方法,这样做真的是很明智的。jetty服务器中的WebAppClassLoader没有tomcat中的classLoader那么智能,他们真的需要改进一下。

下面的类也可以达到关闭jar文件的功能,他通过java中反射机制强行的关闭被打开的JarFile文件,但是这么做的话就依赖于jdk中的URLClassLoader的实现了,对于IBM或WEBLogic中的jdk可能不能运行。

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarFile;

public class TestClassLoader {

	public static void main(String[] args) throws Exception {
		File jar = new File("d:\\test\\commons-lang-2.2.jar");
		URL[] urls = new URL[]{jar.toURI().toURL()};
		URLClassLoader loader = new URLClassLoader(urls);
		Class<?> cls = loader.loadClass("org.apache.commons.lang.StringUtils");
		System.out.println(cls.getName());
		
		// 查找URLClassLoader中的ucp
		Object ucpObj = null;
		Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
		ucpField.setAccessible(true);
		ucpObj = ucpField.get(loader);
		URL[] list = loader.getURLs();
		for(int i=0;i<list.length;i++){
			// 获得ucp内部的jarLoader
			Method m = ucpObj.getClass().getDeclaredMethod("getLoader", int.class);
			m.setAccessible(true);
			Object jarLoader = m.invoke(ucpObj, i);
			String clsName = jarLoader.getClass().getName();
			if(clsName.indexOf("JarLoader")!=-1){
				m = jarLoader.getClass().getDeclaredMethod("ensureOpen");
				m.setAccessible(true);
				m.invoke(jarLoader);
				m = jarLoader.getClass().getDeclaredMethod("getJarFile");
				m.setAccessible(true);
				JarFile jf = (JarFile)m.invoke(jarLoader);
				// 释放jarLoader中的jar文件
				jf.close();
				System.out.println("release jar: "+jf.getName());
			}
		}
	}
}
 
分享到:
评论
5 楼 liang5233145 2016-03-25  
1.7版本,有个close()方法,但是1.7之前没有关闭方法,,这些天也遇到这个问题,因为各种原因,要用1.6版本的jdk,经测试,楼主方法没问题,但是tomact下,这句 URLClassLoader loader = new URLClassLoader(urls);  应改为      URLClassLoader loader = new URLClassLoader(urls,Thread.currentThread().getContextClassLoader());  报错的同学,可以试着改下这句。
4 楼 di1984HIT 2013-05-22  
1.7提供close方法了。比较方便啊
3 楼 weifly 2011-07-10  
feng1018 写道
你用的是jdk版本是?我的是1.5调试时,没用 m = jarLoader.getClass().getDeclaredMethod("ensureOpen");  
这个方法,我去掉这个方法,可以进行jarfile.close,但是对应的jar文件还是不能进行修改/删除操作啊。


tomcat的webClassLoader自己来管理这些被打开的jar文件,没有用父类(URLClassloader)中的变量,因此你调用URLClassloader中的方法关闭jar文件是不管用的,应该调用tomcat的WebClassloader中的方法
2 楼 feng1018 2011-07-05  
大侠,你怎么用的,我在程序删除web-inf/lib下面的包,删除不了
调用 closeJAR()方法后,获取web-inf/lib下面的jar包,直接file.delete()但删除不了,直接在电脑里面删除也删除不了,只有关了tomcat才能删除(我使用tomcat)
private void closeJAR() throws Exception{
URLClassLoader loader = (URLClassLoader) getClass().getClassLoader();   
//((WebappClassLoader)loader).closeJARs(true);
        // 查找URLClassLoader中的ucp  
        Object ucpObj = null;  
        Field ucpField = URLClassLoader.class.getDeclaredField("ucp");  
        ucpField.setAccessible(true);  
        ucpObj = ucpField.get(loader);  
        URL[] list = loader.getURLs();  
        for(int i=0;i<list.length;i++){  
            // 获得ucp内部的jarLoader  
            Method m = ucpObj.getClass().getDeclaredMethod("getLoader", URL.class);  
            m.setAccessible(true);  
            Object jarLoader = m.invoke(ucpObj, list[i]);  
            String clsName = jarLoader.getClass().getName();  
            if(clsName.indexOf("JarLoader")!=-1){  
               // m = jarLoader.getClass().getDeclaredMethod("ensureOpen");  
               // m.setAccessible(true);  
               // m.invoke(jarLoader);  
                m = jarLoader.getClass().getDeclaredMethod("getJarFile", URL.class);  
                m.setAccessible(true);  
                JarFile jf = (JarFile)m.invoke(jarLoader, list[i]);  
                // 释放jarLoader中的jar文件  
                jf.close();  
                jf = null;
                System.out.println("release jar: "+jf.getName());  
            }  
        }  
}
1 楼 feng1018 2011-07-05  
你用的是jdk版本是?我的是1.5调试时,没用 m = jarLoader.getClass().getDeclaredMethod("ensureOpen");  
这个方法,我去掉这个方法,可以进行jarfile.close,但是对应的jar文件还是不能进行修改/删除操作啊。

相关推荐

    Java URLClassLoader动态加载jar包1

    然后,使用`Class.forName()`方法,指定了要加载的类全名(包括包名)"org.javaweb.url.Url",并传入`URLClassLoader`实例作为上下文类加载器,这样就可以确保这个类是由这个特定的`URLClassLoader`加载的。...

    使用URLClassLoader加载本地文件夹c盘下的test.jar文件

    本篇文章将深入讲解如何使用URLClassLoader加载C盘下的test.jar文件。 首先,了解类加载器的基本概念。在Java中,类加载器是负责查找并加载类的机制。Java虚拟机(JVM)使用一系列的类加载器,包括Bootstrap ...

    解决classloader的jar包

    包括commons-logging commons-beanutils commons-lang ezmorph json-lib-2.4-jdk15 commons-collections-3.2.1的jar包,可以解决 org/apache/commons/lang/exception/NestableRuntimeException的问题

    URLClassLoader中指定目录和jar的问题

    - JAR文件内部的类加载同样遵循包结构,`URLClassLoader`会解析JAR的`META-INF/MANIFEST.MF`文件,如果存在`Class-Path`属性,还会加载指定的其他JAR。 5. **动态添加URL**: - 由于`URLClassLoader`的`addURL`...

    Eclipse打包成JAR包读取外部JAR包和外部配置文件

    本文将详细介绍如何在Eclipse中将项目打包成JAR文件,并确保能正确引用外部JAR包和读取外部配置文件。 首先,我们来看如何打包项目为JAR。在Eclipse中,选择`Export` -&gt; `Java` -&gt; `Runnable JAR file`。在弹出的...

    jar包隔离代码.zip

    2. 使用URLClassLoader:通过URL数组指定jar的路径,每个URL代表一个jar,可以控制不同版本的jar包加载顺序。 3. 配置管理:创建配置文件,记录各个模块所依赖的jar包版本,根据配置动态加载对应的jar包。 4. 使用...

    jar包、class文件读取工具

    常见的工具有JD-GUI,它是一个图形界面工具,可以直接打开jar包或class文件,显示源代码视图。 三、JD-GUI的使用 1. 安装与启动:JD-GUI是一个独立的工具,可以从官方网站下载安装。启动后,通过菜单或拖放方式可以...

    Springboot + Hutool-db 使用 URLClassLoader 动态加载外部数据库和数据池 jar包实例

    在这个场景中,我们看到一个基于Springboot的应用程序结合了Hutool-db库,利用URLClassLoader来实现动态加载外部数据库驱动和数据池的jar包。这使得开发者可以在不重启应用的情况下更新或添加新的数据库连接和资源池...

    Spring bean 动态注册,jar包热替换

    Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class文件,动态实现spring bean 的动态加载,并通过UrlClassLoader完成jar和class文件的加载。可以实现jar的热替换。spring的bean动态加载则需要对...

    Struct jar 包

    在本资源中,"structure开发"可能是指一种特定的软件架构或开发框架,它被封装在一个JAR包内,供开发者在构建应用程序时使用。 1. **Java JAR 文件**: JAR文件是Java平台的核心组成部分,它允许将多个类文件、资源...

    Java源文件读取JAR包文件.rar

    在Java编程中,有时我们需要在运行时从JAR(Java ...通过以上步骤,你可以在Java源文件中成功地读取并处理JAR包文件中的内容。记住,这只是一个基础的实现,根据具体需求,你可能需要添加更多的错误处理和优化措施。

    定义ClassLoader调用外部jar包

    在处理外部jar包时,我们可能需要从文件系统或网络读取类的`.class`文件,这可以通过`URLClassLoader`的子类实现,它提供了方便的方法来加载基于URL的类。 以下是一个简单的自定义ClassLoader示例,它能从指定的jar...

    ofdrw .ofd 转 .pdf 所需要的jar包,不是maven项目的看过来.rar

    在标题和描述中提到的"ofdrw .ofd 转 .pdf 所需要的jar包,不是maven项目的看过来.rar",这表明这个压缩包包含了一组Java库(jar包),用于非Maven项目中将OFD文件转换为PDF。 首先,我们需要理解什么是OFD和PDF。...

    解析apk的jar包

    "解析apk的jar包"就是这样一个工具,它可以帮助我们提取和查看APK中的重要信息,比如版本号、版本名以及包名等。 首先,我们要了解APK的结构。一个标准的APK文件实际上是一个ZIP格式的压缩包,里面包含了DEX...

    aop面向切面需要的jar包

    在使用spring的aop功能时,这两个jar是必须的,否则会报错,如下: Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException at java.net....

    java动态添加外部jar包到classpath的实例详解

    URLClassLoader是一个专门用于加载外部jar包的类加载器,它可以从外部jar包中加载类文件。我们可以使用URLClassLoader来加载外部jar包,然后将其添加到classpath中。 下面是一个使用URLClassLoader加载外部jar包的...

    我的平台使用的jar包2

    "我的平台使用的jar包2"可能指的是这个平台依赖的一个关键组件,可能是用于提供特定功能或者服务的库。 在Java开发中,JAR文件扮演着至关重要的角色。它们是程序的可执行部分,通常包含了类、接口、元数据和资源...

    springboot动态加载jar包到容器中,并映射为接口

    ### Spring Boot 动态加载 Jar 包到容器中并映射为接口的技术解析 #### 一、背景介绍 在实际的开发过程中,我们经常会遇到这样的需求:系统需要根据不同的业务场景来动态地加载不同的功能模块或者组件。这些功能...

    加载jar包中的spring配置文件

    `classpath*:`不仅会查找类路径下的指定资源,还会递归地查找所有jar包和目录下的匹配文件。这意味着如果你有多个相同命名的配置文件分别存在于不同的jar包中,`classpath*:`会找到所有这些文件。 4. **Spring的...

    JAVA项目开发案例全程实录(第2版)jar包资源下载

    jar包是Java应用程序的可执行格式,它包含编译后的类文件和其他资源,使得开发者可以方便地分发和运行Java程序。 在提供的压缩文件"JAVAxmqcsljar"中,我们很可能找到了与本书案例相关的jar包资源。这个jar包可能是...

Global site tag (gtag.js) - Google Analytics