最近在考虑C/S结构程序的软件自动升级的实现方式,比如QQ、飞信等都自动升级的功能。

自动升级模块虽然还没有编码完成,但是思路还是比较清晰的。

自动升级过程中,升级文件的JAR包是专门加载到程序中去的,因此,自定义一个ClassLoader,用于加载用户JAR包,就非常的重要了。

应用程序ClassLoader只提供了一个public Class<?> loadClass(String name) throws ClassNotFoundException 方法,没有提供加载JAR的方法。

URLClassLoader提供了一个protected void addURL(URL url)的方法,倒是可以加载JAR包,但苦于非public的。

经测试发现,AppClassLoader是URLClassLoader的子类。因此,我们完全可以利用URLClassLoader了哦。

  1. URLClassLoader system = (URLClassLoader) ClassLoader.getSystemClassLoader();
URLClassLoader system = (URLClassLoader) ClassLoader.getSystemClassLoader();

这样,我们可以通过反射得到addURL方法,在程序中加载我们自己的JAR包了。

整个源代码如下所示:

  1. /**
  2. * Copyright (c) YMCN Team
  3. * All rights reserved.
  4. */
  5. package com.aboy.toolkit.util;
  6. import java.io.File;
  7. import java.lang.reflect.Method;
  8. import java.net.URL;
  9. import java.net.URLClassLoader;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. /**
  13. * @author obullxl
  14. *
  15. * email: obullxl@163.com  MSN: obullxl@hotmail.com  QQ: 303630027
  16. *
  17. * Blog: http://obullxl.iteye.com
  18. */
  19. public final class ClassLoaderUtil {
  20. /** URLClassLoader的addURL方法 */
  21. private static Method addURL = initAddMethod();
  22. /** 初始化方法 */
  23. private static final Method initAddMethod() {
  24. try {
  25. Method add = URLClassLoader.class
  26. .getDeclaredMethod("addURL", new Class[] { URL.class });
  27. add.setAccessible(true);
  28. return add;
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32. return null;
  33. }
  34. private static URLClassLoader system = (URLClassLoader) ClassLoader.getSystemClassLoader();
  35. /**
  36. * 循环遍历目录,找出所有的JAR包
  37. */
  38. private static final void loopFiles(File file, List<File> files) {
  39. if (file.isDirectory()) {
  40. File[] tmps = file.listFiles();
  41. for (File tmp : tmps) {
  42. loopFiles(tmp, files);
  43. }
  44. } else {
  45. if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
  46. files.add(file);
  47. }
  48. }
  49. }
  50. /**
  51. * <pre>
  52. * 加载JAR文件
  53. * </pre>
  54. *
  55. * @param file
  56. */
  57. public static final void loadJarFile(File file) {
  58. try {
  59. addURL.invoke(system, new Object[] { file.toURI().toURL() });
  60. System.out.println("加载JAR包:" + file.getAbsolutePath());
  61. } catch (Exception e) {
  62. e.printStackTrace();
  63. }
  64. }
  65. /**
  66. * <pre>
  67. * 从一个目录加载所有JAR文件
  68. * </pre>
  69. *
  70. * @param path
  71. */
  72. public static final void loadJarPath(String path) {
  73. List<File> files = new ArrayList<File>();
  74. File lib = new File(path);
  75. loopFiles(lib, files);
  76. for (File file : files) {
  77. loadJarFile(file);
  78. }
  79. }
  80. }
/**
* Copyright (c) YMCN Team
* All rights reserved.
*/
package com.aboy.toolkit.util; import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List; /**
* @author obullxl
*
* email: obullxl@163.com MSN: obullxl@hotmail.com QQ: 303630027
*
* Blog: http://obullxl.iteye.com
*/
public final class ClassLoaderUtil {
/** URLClassLoader的addURL方法 */
private static Method addURL = initAddMethod(); /** 初始化方法 */
private static final Method initAddMethod() {
try {
Method add = URLClassLoader.class
.getDeclaredMethod("addURL", new Class[] { URL.class });
add.setAccessible(true);
return add;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} private static URLClassLoader system = (URLClassLoader) ClassLoader.getSystemClassLoader(); /**
* 循环遍历目录,找出所有的JAR包
*/
private static final void loopFiles(File file, List<File> files) {
if (file.isDirectory()) {
File[] tmps = file.listFiles();
for (File tmp : tmps) {
loopFiles(tmp, files);
}
} else {
if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
files.add(file);
}
}
} /**
* <pre>
* 加载JAR文件
* </pre>
*
* @param file
*/
public static final void loadJarFile(File file) {
try {
addURL.invoke(system, new Object[] { file.toURI().toURL() });
System.out.println("加载JAR包:" + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
} /**
* <pre>
* 从一个目录加载所有JAR文件
* </pre>
*
* @param path
*/
public static final void loadJarPath(String path) {
List<File> files = new ArrayList<File>();
File lib = new File(path);
loopFiles(lib, files);
for (File file : files) {
loadJarFile(file);
}
}
}

在程序中,只要使用上面最后两个方法,就可以加载自定义JAR包和一个目录中的所有JAR包了。

经本人测试,上面代码运行无误,能正常加载自定义JAR包。

欢迎指正~~~~~~~

自定义ClassLoader,用于加载用户JAR包的更多相关文章

  1. (转)自定义ClassLoader ----可以加载第三方jar包

    package com.classloader.util; import java.io.IOException; import java.net.MalformedURLException; imp ...

  2. 加载所有jar包下指定文件

    加载所有jar包下指定文件: 如spring中加载 META-INF/spring.handlers 加载 org.springframework.core.io.support.Properties ...

  3. Spark on Yarn运行时加载的jar包

    spark on yarn运行时会加载的jar包有如下: spark-submit中指定的--jars $SPARK_HOME/jars下的jar包 yarn提供的jar包 spark-submit通 ...

  4. maven加载本地jar包到repository

    maven加载本地jar到repository 这是一个常见场景,此处以本地opencv jar文件导入repository为例 1.Ubuntu下 mvn install:install-file ...

  5. 27 Java动态加载第三方jar包中的类

    我加载的方法是://参数fileName是jar包的路径,processorName 是业务类的包名+类名public static A load(String fileName, String pr ...

  6. Gradle加载本地jar包

    有时,我们需要的jar包不一定能在远程仓库中找到,这时我们需要加载本地的jar包. 加载单独的jar包 在项目底下添加libs目录,将jar包仍进libs目录 build.gradle配置如下: de ...

  7. maven无法加载本地jar包以及maven项目打包后本地jar包没有打进项目的问题解决办法

    1.首先设置依赖项,这样maven就会把该路径下的jar包导入项目引用 <dependency> <groupId>DPSDK-Manager</groupId> ...

  8. maven加载第三方jar包

    <dependency> <groupId>com.yeepay</groupId> <artifactId>yop-sdk</artifactI ...

  9. JVM自定义类加载器加载指定classPath下的所有class及jar

    一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...

随机推荐

  1. python+selenium实现动态爬取及selenuim的常用操作

    应用实例可以参考博客中的12306自动抢票应用 https://www.cnblogs.com/mumengyun/p/10001109.html 动态网页数据抓取 什么是AJAX: AJAX(Asy ...

  2. React with webpack

    //entry.js require("!style!css!./style.css"); require("./hello.jsx"); // documen ...

  3. IDEA-Debug调试操作

    基本概念 快捷键和eclipse还是有区别的,不过基本概念是相通的   Step into F7 单步调试进入函数内部.  Step over F8 单步调试不进入函数内部,如果装了金山词霸2006则 ...

  4. 20155327 嵌入式C语言课堂补交

    嵌入式C语言 题目要求 在作业本上完成附图作业,要认真看题目要求. 提交作业截图 作弊本学期成绩清零(有雷同的,不管是给别人传答案,还是找别人要答案都清零) 题目分析 分析一:提取插入时间 根据老师上 ...

  5. WPF RoutedEvent and HitTest - 简书

    原文:WPF RoutedEvent and HitTest - 简书 学习的时候切忌心浮气躁,慢慢的过每一个知识点,不要漏掉任何细节.不然当遇到细节问题的时候,会恼,会闹,会悔不该当初--花一下午调 ...

  6. 苏州Uber优步司机奖励政策(4月18日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. [POI2011]MET-Meteors

    题面 题解 首先我们尝试暴力,那么就对每个点二分一下即可. 我们发现单独二分复杂度太高,而且有些地方很浪费,如求前缀和等. 那么我们就想,能否将它们合并在一起二分呢? 于是就有了整体二分 整体二分即可 ...

  8. LOJ #2585. 「APIO2018」新家

    #2585. 「APIO2018」新家 https://loj.ac/problem/2585 分析: 线段树+二分. 首先看怎样数颜色,正常的时候,离线扫一遍右端点,每次只记录最右边的点,然后查询左 ...

  9. 海思NB-IOT的SDK里面写KV键值对值掉电保存参数

    1. 写函数,ICCID_CTRL_KEY  这个是键,有些是海思已经使用的,所以自己定义的时候要错开,函数的第二个参数是数据指针,第三个参数是数据长度 #define ICCID_CTRL_KEY ...

  10. SSM-CRUD实战

    前端最容易出现缓存问题,所以以后每次都必须完全在idea加载完后,再在浏览器端多 执行 ctrl+F5 索要最新copy 这样就能拿到最新的改动了,就不会出现各种代码没问题但是功能就是实现不了的问题 ...