`

自定义ClassLoader

    博客分类:
  • JDK
阅读更多
 package com.classloader.util;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.util.Enumeration;
import java.util.jar.Manifest;

public class NetworkClassLoader extends URLClassLoader {

	String baseUrl;

	public String getBaseUrl() {
		return baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	public NetworkClassLoader(){
		this(new URL[]{});
	}

	/**
	 * URL 以'/'结尾的为目录
	 *     否则为jar包
	 *     未指定其父类加载器为系统类加载器
	 * @param urls
	 */
	public NetworkClassLoader(URL[] urls) {
		super(urls);
	}

	/**
	 * 同上,指定classLoader
	 * @param urls
	 * @param parent
	 */
	public NetworkClassLoader(URL[] urls, ClassLoader parent) {
		super(urls,parent);
	}

	/**
	 * 同上,URL工厂处理器
	 * @param urls
	 * @param parent
	 * @param factory
	 */
	public NetworkClassLoader(URL[] urls, ClassLoader parent,
			  URLStreamHandlerFactory factory) {
		 super(urls,parent,factory);
	}

	/**
	 * [添加baseUrl]
	 * @param url
	 */
	public void addURL(String url){
		URL uurl=null;
		try {
			uurl = new URL(baseUrl+url);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		addURL(uurl);
	}

	/**
	 * 添加url[添加baseUrl]
	 */
	protected void addURL(URL url) {
		super.addURL(url);
	}

	/**
	 * 返回urls
	 */
	public URL[] getURLs() {
		return super.getURLs();
	}

	/**
	 * 查找类对象
	 *   从以上的URLS中查找加载当前类对象[会打开所有的jars去查找指定的类]
	 *   (可以通过调用findClass来得到以上URL加载包中的类)
	 */
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		return super.findClass(name);
	}

	/**
	 * defineClass SecureClassLoader定义为最终方法,不允许更改.
	 * 在使用这个类对象前,必须先resolved(解析)
	 */


	/**
	 * 查找资源[自定义相对URL查找路径]
	 *   从以上的URLS中查找当前名称的资源
	 * 这个必须重写,因为是public 哈哈
	 */
	public URL findResource(String name) {
		URL url = null;
		try {
			url = new URL(baseUrl+name);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return url;
	}

	/**
	 * 查找资源列表[URL查找路径]
	 */
	public Enumeration<URL> findResources(String name) throws IOException {
		return super.findResources(name);
	}

	/**
	 * 在当前的ClassLoader中,定义一个新的Package,Package的属性由Manifest指定.这个包的源文件
	 */
	protected Package definePackage(String name, Manifest man, URL url)
			throws IllegalArgumentException {
		return super.definePackage(name, man, url);
	}

	/**
	 * 加载路径权限
	 */
	protected PermissionCollection getPermissions(CodeSource codesource) {
		return super.getPermissions(codesource);
	}
}


以下是用法:
	NetworkClassLoader loader = new NetworkClassLoader();
		loader.setBaseUrl("file:///F:\\框架\\maven\\app\\jms\\src\\main\\webapp\\modules\\");

		loader.addURL("App/lib/test.jar");
		loader.addURL("App/lib/test1.jar");
		loader.addURL("App/template/view.vm");
		loader.addURL("App/config.xml");

这里初始化了此类加载器所使用的类资源,配置文件等。
以下是如何加载类资源:
Class clazz= loader.findClass("com.jvm.look.A");//加载类

以下是加载配置文件资源
URL uuu = loader.findResource("App/config.xml");

有一点需要注意的,这个类加载器还是双亲委托机制,比如有一个类"com.annotation.table.Test"在父类加载器中如果已经加载过了,那么如果这个类在test.jar中存在,那么不会重新定义加载,而使用父类加载器加载的类,有人问了,那我如何覆盖父类加载器中定义的类。
可以进行如下操作:
Class clazz2= loader.findClass("com.annotation.table.Test");

重新加载类,类的加载序列我在上一篇已经讲过了,不熟悉的可以看以上文章.
可能有人会问了,如果每一个类都这样,那我不崩溃了,我需要把我加载的jar覆盖父类加载器中定义的所有类.

	/**
	 * 覆盖父加载器中定义的类,使用当前类加载器加载资源,那么所有的类都在此加载器中执行.
	 * 这样,所有URL中的类都通过此类加载器加载,也就是说URL中的类的定义类加载器就是当前类加载器.
	 * 建议:尽量不要使用这种方式覆盖父加载器定义的类.[按一种约定双亲委托机制加载]
	 * (如果重载了,那么尽量使用此loader加载类,这样所有逻辑都在此ClassLoader中运行,当然还有SDK还是从双亲加载)
	 * 可以在SDK中定义接口,在此JAR里面提供实现.
	 */
	public void initAllJar(){
		URL[] urls = this.getURLs();

		for(URL urll:urls){
			String url = urll.getFile();
			//重新定义这个架包中的所有类.
			if(url.endsWith("jar")){
				File jarFile  = getJarFile(url);
				JarFile jarFileTemp = null;
				try {
					jarFileTemp = new JarFile(jarFile);
					Enumeration<JarEntry> en = jarFileTemp.entries();
					while (en.hasMoreElements()) {
						JarEntry je = en.nextElement();
						String name = je.getName();
						if (name.endsWith(CLASS_FILE)) {
							String className = name.substring(0, name.length()
									- CLASS_FILE.length());
							findClass(pathToDot(className));
						}
					}

				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

/**
	 * 转jar包路径和jar文件名为具体文件.
	 *
	 * @param root
	 * @param jar
	 * @return
	 */
	private File getJarFile(String file) {
		if (file.startsWith(PREFIX_FILE))
			file = file.substring(PREFIX_FILE.length());
		int end = file.indexOf(JAR_URL_SEPERATOR);
		if (end != (-1))
			file = file.substring(0, end);
		return new File(file);
	}

   /**
     * 转路径为包名[/ ==> .]/[\\ ==> .]
     * @param s
     * @return
     */
    private String pathToDot(String s) {
        return s.replace('/', '.').replace('\\', '.');
    }


其实JDK中已经提供了好几个ClassLoader,大家可以扩展,比如项目中有两个架包版本,结构全部都一样,但是两个架包都必须运行。这时自定义类加载器就有用了。
0
2
分享到:
评论
1 楼 zxjlwt 2015-10-12  
学习了。

http://surenpi.com

相关推荐

    自定义classloader的使用

    自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨自定义Classloader的使用。 一、Classloader的工作原理 Java的类加载机制遵循双亲...

    Java实现热加载完整代码;Java动态加载class;Java覆盖已加载的class;Java自定义classloader

    让Java支持热加载是个不错的想法。如何做到的呢? 1. 定义好接口和实现类 2. 让代理类通过反射的方式调用实现类,对外暴露的是代理类。 3. 自定义URLClassLoader。检查实现类.class文件的...Java自定义classloader;

    定义ClassLoader调用外部jar包

    当我们需要从外部jar包动态加载类时,自定义ClassLoader就显得尤为关键。这篇博文"定义ClassLoader调用外部jar包"探讨了如何创建一个自定义的ClassLoader,以便能够灵活地加载不在应用主类路径(ClassPath)中的jar...

    ClassLoader运行机制 自己写的

    这里我们将详细讨论ClassLoader的运行机制,特别是自定义ClassLoader的设计与实现。 ClassLoader的基本职责是根据类名动态加载对应的类文件。在Java中,类加载过程遵循双亲委派模型(Parent Delegation Model)。这...

    使用自定义ClassLoader解决反序列化serialVesionUID不一致问题 _ 回忆飘如雪1

    标题和描述中提到的解决方案是通过自定义`ClassLoader`来处理`serialVersionUID`不一致的问题。以下是几种常见方法的优缺点以及自定义`ClassLoader`的详细解释: 1. **修改序列化byte数据**: 这种方法直接修改已...

    关于Android中自定义ClassLoader耗时问题的追查

    在Android开发中,自定义ClassLoader是一项关键技能,尤其在实现热修复和插件化技术时。本文主要探讨了Android中自定义ClassLoader导致的性能问题,特别是冷启动速度的影响。问题的核心在于,通过插入自定义的...

    MyCLRepl:自定义 Scala REPL 示例以添加自定义 ClassLoader 和自定义 REPL 命令

    自定义 ClassLoader 加载任何类时的类名。 ":myCommand" 命令位于默认 REPL 命令之上。 scala &gt; val hello = " hello " MyClassLoader loads classOf &lt; root&gt;.$line3 &lt;&lt;中略&gt;&gt; MyClassLoader loads classOf ...

    ClassLoader 案例

    自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热部署等。本案例将深入探讨如何创建一个自定义的ClassLoader,利用Java反射和注解技术...

    ClassLoader小例子

    下面我们将详细讨论ClassLoader的基本概念、工作流程以及如何自定义ClassLoader。 1. **ClassLoader的基本概念** - 类加载器是Java中的一个核心组件,它负责将类的.class文件加载到JVM中,并转换为可执行的Java...

    classloader

    创建自定义类加载器需要继承ClassLoader类,并重写findClass()方法。在这个方法里,你可以编写代码来从指定的位置(例如,网络、文件系统或内存)读取类的字节码,并通过defineClass()方法将其转换为Class对象。 在...

    Java ClassLoader定制实例

    在某些特定场景下,比如动态加载代码、插件系统或者安全隔离等,我们需要自定义ClassLoader来实现特定的加载逻辑。例如,我们可能希望加载网络上的类,或者从数据库中读取类的字节码。 以...

    Understanding the Java ClassLoader

    为了更好地理解和利用Java的这一特性,本篇将详细介绍Java ClassLoader的作用及其工作原理,并通过构建一个示例ClassLoader来帮助读者深入理解如何自定义ClassLoader,从而扩展JVM的功能。 #### 二、ClassLoader...

    ClassLoader类加载器

    了解和掌握ClassLoader的工作原理以及如何自定义ClassLoader对于深入理解Java应用程序的运行机制非常有帮助。以下是对ClassLoader API的使用和自定义的详细说明。 首先,我们来看ClassLoader的基本概念。在Java中,...

    ClassLoader类加载机制和原理详解

    但有时我们可能需要打破这种模型,比如实现类的版本控制或插件系统,这时可以通过自定义ClassLoader来实现。 5. 类加载器的关系图 Java中的ClassLoader形成了一个树状结构,Bootstrap ClassLoader位于顶端,其他类...

    ClassLoader的 一些测试

    自定义ClassLoader是一种常见的需求,例如在插件系统、热部署等场景。自定义加载器通常需要重写`loadClass(String className)`方法,通过URL读取类的字节流并转换为Class对象。在这个过程中,我们需要注意类的缓存,...

    理解Java ClassLoader机制

    自定义ClassLoader需要继承`java.lang.ClassLoader`类,并重写`findClass()`或`loadClass()`方法。通过这两个方法,你可以控制类的加载来源和方式。 在实际开发中,理解ClassLoader机制可以帮助解决一些问题,例如...

    ClassLoader 详解.doc

    自定义ClassLoader是Java平台的一大特色,开发人员可以根据需要创建自己的类加载器,例如实现模块化、热部署或者加密解密类等高级功能。自定义ClassLoader通常需要重写findClass()或loadClass()方法,以控制类的加载...

    java classloader

    在Java中,用户可以通过自定义ClassLoader来实现特定的加载逻辑,比如从数据库或网络中加载类。这使得Java可以支持许多高级功能,例如插件系统、热部署和模块化系统(如Java 9的Jigsaw项目)。 `JAVA2深度历险.jpg`...

    浅析ClassLoader

    1. 自定义需求:在某些场景下,如动态加载插件、加密类文件等,开发者可能需要自定义ClassLoader。自定义ClassLoader需要继承java.lang.ClassLoader并重写findClass()方法。 2. 实现步骤:创建类加载器实例,读取类...

Global site tag (gtag.js) - Google Analytics