备注:java加载jar包文件和class文件核心代码参考了Alvin-Qu的Java中动态加载jar文件和class文件文章
解压缩zip的核心代码
/**
* 解压缩
*
* @param srcFile
* @param destFile
* @throws Exception
*/
public static void decompress(File srcFile, File destFile) throws Exception {
CheckedInputStream cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
ZipInputStream zis = new ZipInputStream(cis);
decompress(destFile, zis);
zis.close();
}
动态加载jar包和某个class文件的处理类
public class DynamicLoaderCustomClassOrProjectPackageFileUtil {
/** 日志*/private static final Logger LOGGER = LoggerFactory
.getLogger(DynamicLoaderCustomClassOrProjectPackageFileUtil.class);
public static boolean loadJarFile(String filePath, String targetPath,String fileName){
// String zipFilePath = "D:\\lzTest\\classFile\\fcalljar.zip";//待解压文件
// String decompressFilePath = "D:\\lzTest\\classFile";//解压后文件
try {
//解压zip文件
ZipUtil.decompress(filePath, targetPath);//加载jar包文件
String jarClassFilePath = targetPath+"/"+fileName+"/jarPackage";
TestDynamicClassJarTest.loadJarClassFile(jarClassFilePath);
//加载自行编写的class文件 必须是:类路径下完整路径
//例如/usr/java/classes下有一个test.App类,则/usr/java/classes即这个类的根路径,而.class文件的实际位置是/usr/java/classes/test/App.class
String classFilePath = targetPath+"/"+fileName+"/customScriptClass";
TestDynamicClassJarTest.loadClassFile(classFilePath);
} catch (Exception e) {
LOGGER.error("load class wenjian失败!!!", e);
}
return true;
}
private static void loadJarPackageFile(String jarClassFilePath) throws MalformedURLException,
SecurityException,
NoSuchMethodException {
// 系统类库路径
File libPath = new File(jarClassFilePath);
// 获取所有的.jar和.zip文件
File[] jarFiles = libPath.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar") || name.endsWith(".zip");
}
});
for (File f : jarFiles) {
System.out.println(f.getAbsolutePath() + "/" + f.getName());
}
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);
System.out.println("读取jar文件[name={}]" + file.getName());
} catch (Exception e) {
System.out.println("读取jar文件[name={}]失败" + file.getName());
}
}
} finally {
method.setAccessible(accessible);
}
}
}
/**
* 动态加载指定文件目录的class文件到jvm
*
* @param classFilePath java的class文件路径
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
* @throws MalformedURLException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws ClassNotFoundException
*/
private static void loadClassFile(String classFilePath) throws SecurityException,
NoSuchMethodException,
IllegalArgumentException,
MalformedURLException,
IllegalAccessException,
InvocationTargetException,
ClassNotFoundException {
// 设置class文件所在根路径
// 例如/usr/java/classes下有一个test.App类,则/usr/java/classes即这个类的根路径,而.class文件的实际位置是/usr/java/classes/test/App.class
File clazzPath = new File(classFilePath);
// 记录加载.class文件的数量
int clazzCount = 0;
if (clazzPath.exists() && clazzPath.isDirectory()) {
// 获取路径长度
int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;
Stack<File> stack = new Stack<File>();
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类
//LOGGER.info("---加载的class-----" + className);
Class.forName(className);
System.out.println("读取应用程序类文件[class={}]" + className);
}
}
}
}
}
}