- 前言
- 相关概念
- 什么是JarUrlConnetion
- jar协议格式
- 功能
- 获取JarFile
- 遍历JarEntry
- 执行class文件
- Manifest
前言
最近研究关于classloader,实现对模块的热插拔和类替换等功能。然后意外发现一个用于处理JAR包的官方库。
相关概念 什么是JarUrlConnetionjarUrlConnection通过Jar协议建立一个访问jar包的连接,可以访问这个jar包内部数据
jar协议格式jar协议的格式如:jar:{archive-url}!/{entry}。
- archive-url是文件地址
- !/是分隔符
- entry是jar包内部的目录或者文件
示例:
- 访问远程http服务器
- 整个jar包。jar:http://www.zsmile.top/test.jar!/
- jar包内的文件。jar:http://www.zsmile.top/test.jar!/Hello.class
- jar包内的目录。jar:http://www.zsmile.top/test.jar!/top/smile/
- 访问本地文件系统
- 整个jar包。jar:file://E:/test.jar!/
- jar包内的文件。jar:file://E:/test.jar!/Hello.class
- jar包内的目录。jar:file://E:/test.jar!/top/smile/
URL url = new URL("jar:file://E:/test.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
JarFile jarfile = conn.getJarFile();
遍历JarEntry
Enumeration执行class文件entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); System.out.println(jarEntry.getName() + " is directory :" + jarEntry.isDirectory()); }
// 获取class数据流
InputStream inputStream = jarFile.getInputStream(jarEntry);
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes);
// 借助classloader的defineClass将byte转换成class对象
Class> aClass = defineClass("top.zsmile.jvm.classloader.Hello", bytes, 0, bytes.length);
// 通过反射调用方法
Method method = aClass.getMethod("main", String[].class);
method.invoke(null, (Object) null);
Manifest
Manifest mainfest = jarfile.getManifest();
// 获取并遍历属性
System.out.println("manifest Attributes:");
Attributes mainAttributes = manifest.getMainAttributes();
Set> entries = mainAttributes.entrySet();
for (Map.Entry 


