• Java动态加载jar及class文件


        经常碰到需要动态加载jar及class文件的场景。Java类由于需要加载和编译字节码,动态加载class文件较为麻烦,但JDK仍提供了一整套方法来动态加载jar文件和class文件。

    一、动态加载jar

    // 系统类库路径
    File libPath = new File(jar文件所在路径);
    
    // 获取所有的.jar和.zip文件
    File[] jarFiles = libPath.listFiles(new FilenameFilter() {
    	public boolean accept(File dir, String name) {
    		return name.endsWith(".jar") || name.endsWith(".zip");
    	}
    });
    
    if (jarFiles != null) {
    	// 从URLClassLoader类中获取类所在文件夹的方法
    	// 对于jar文件,可以理解为一个存放class文件的文件夹
    	Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    	boolean accessible = method.isAccessible();		// 获取方法的访问权限
    	try {
    		if (accessible == false) {
    			method.setAccessible(true);		// 设置方法的访问权限
    		}
    		// 获取系统类加载器
    		URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    		for (File file : jarFiles) {
    			URL url = file.toURI().toURL();
    			try {
    				method.invoke(classLoader, url);  
    				LOG.debug("读取jar文件[name={}]", file.getName());
    			} catch (Exception e) {
    				LOG.error("读取jar文件[name={}]失败", file.getName());
    			}
    		}
    	} finally {
    		method.setAccessible(accessible);
    	}
    }
    

     二、动态加载class文件

    // 设置class文件所在根路径
    // 例如/usr/java/classes下有一个test.App类,则/usr/java/classes即这个类的根路径,而.class文件的实际位置是/usr/java/classes/test/App.class
    File clazzPath = new File(class文件所在根路径);
    
    // 记录加载.class文件的数量
    int clazzCount = 0;
    
    if (clazzPath.exists() && clazzPath.isDirectory()) {
    	// 获取路径长度
    	int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;
    
    	Stack<File> stack = new Stack<>();
    	stack.push(clazzPath);
    
    	// 遍历类路径
    	while (stack.isEmpty() == false) {
    		File path = stack.pop();
    		File[] classFiles = path.listFiles(new FileFilter() {
    			public boolean accept(File pathname) {
    				return pathname.isDirectory() || pathname.getName().endsWith(".class");
    			}
    		});
    		for (File subFile : classFiles) {
    			if (subFile.isDirectory()) {
    				stack.push(subFile);
    			} else {
    				if (clazzCount++ == 0) {
    					Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    					boolean accessible = method.isAccessible();
    					try {
    						if (accessible == false) {
    							method.setAccessible(true);
    						}
    						// 设置类加载器
    						URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    						// 将当前类路径加入到类加载器中
    						method.invoke(classLoader, clazzPath.toURI().toURL());
    					} finally {
    						method.setAccessible(accessible);
    					}
    				}
    				// 文件名称
    				String className = subFile.getAbsolutePath();
    				className = className.substring(clazzPathLen, className.length() - 6);
    				className = className.replace(File.separatorChar, '.');
    				// 加载Class类
    				Class.forName(className);
    				LOG.debug("读取应用程序类文件[class={}]", className);
    			}
    		}
    	}
    }
    

     完成上述两步操作后,即可使用Class.forName来加载jar中或.class文件包含的Java类了。

  • 相关阅读:
    20175318 2018-2019-2 实验一《Java开发环境的熟悉》实验报告
    修改 IntelliJ IDEA 默认配置路径
    《Java程序设计》 第三周学习任务
    计算机网络第七版(谢希仁著)课后习题答案
    VMware虚拟机安装苹果Mac OS
    使用Xshell在Windows系统和Linux系统之间进行文件传输
    python:常用模块
    python:模块
    python:函数
    python字符编码与转码
  • 原文地址:https://www.cnblogs.com/moonandstar08/p/5827806.html
Copyright © 2020-2023  润新知