Java:读取jar文件中的class并创建实例

1. 声明

当前内容主要为本人学习和复习从jar文件中读取class的操作

主要包括:

  1. 使用JarFile方式读取
  2. 使用JarInputStream方式读取

主要参考官方api文档

2. JarFile方式

在这里插入图片描述
Jar就是Zip文件的一种

首先准备一个需要读取的jar(myCommons.jar)

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

/**
 * 
 * @author hy
 * @createTime 2021-06-20 09:41:55
 * @description 读取jar的内容并获得解析(使用jarFile方式)
 *
 */
public class ReadJarTestUsingJarFile {
	public static void main(String[] args) throws MalformedURLException {
		String jarFilePath = "C:\\Users\\admin\\Desktop\\java的测试\\commons-test\\myCommons.jar";

		File file = new File(jarFilePath);

		if (!file.exists()) {
			System.out.println("文件不存在!");
			return;
		}
		if (!file.isFile()) {
			System.out.println("读取的为文件夹而非文件!");
			return;
		}
		if (!file.canRead()) {
			System.out.println("当前文件不可读!");
			return;
		}
		URL url1 = file.toURI().toURL();
		URLClassLoader jarUrlClassLoader = new URLClassLoader(new URL[] { url1 },
				Thread.currentThread().getContextClassLoader());
		JarFile jarFile = null;
		try {
			jarFile = new JarFile(file);
			// 获取jar中实际的MAINFEST.MF文件
			Manifest manifest = jarFile.getManifest();
			pringManifestFile(manifest);
			// 开始获取jar中的.class文件
			Enumeration<JarEntry> entries = jarFile.entries();
			List<String> classNames = getClassNames(entries);
			classNames.forEach(x -> {
				if (x.endsWith("MySQLConnectionCliTest")) {
					loadAndInstanceClass(x, jarUrlClassLoader);
				}
			});

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (jarFile != null) {
				try {
					jarFile.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 
	 * @author hy
	 * @createTime 2021-06-20 10:31:25
	 * @description 加载类和实例化类
	 * @param clazzName
	 * @param classLoader
	 *
	 */
	private static void loadAndInstanceClass(String clazzName, ClassLoader classLoader) {
		try {
			// 需要使用其他的classLoader加载
			Class<?> forName = classLoader.loadClass(clazzName);
			System.out.println(forName);
			try {
				Object newInstance = forName.newInstance();
				System.out.println(newInstance);
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @author hy
	 * @createTime 2021-06-20 10:24:46
	 * @description 打印并获取所有的class
	 * @param entries
	 * @param classloader
	 *
	 */
	private static List<String> getClassNames(Enumeration<JarEntry> entries) {
		List<String> classNames = new ArrayList<String>();
		while (entries.hasMoreElements()) {
			JarEntry nextElement = entries.nextElement();
			String name = nextElement.getName();
			// 这个获取的就是一个实体类class java.util.jar.JarFile$JarFileEntry
			// Class<? extends JarEntry> class1 = nextElement.getClass();
			System.out.println("entry name=" + name);
			// 这样就获取所有的jar中的class文件

			// 加载某个class文件,并实现动态运行某个class
			if (name.endsWith(".class")) {
				String replace = name.replace(".class", "").replace("/", ".");
				classNames.add(replace);
			}
		}
		return classNames;
	}

	/**
	 * 
	 * @author hy
	 * @createTime 2021-06-20 10:32:16
	 * @description 输出当前的manifest文件中的信息内容
	 * @param manifest
	 *
	 */
	private static void pringManifestFile(Manifest manifest) {
		Attributes mainAttributes = manifest.getMainAttributes();
		Set<Entry<Object, Object>> entrySet = mainAttributes.entrySet();
		Iterator<Entry<Object, Object>> iterator = entrySet.iterator();
		// 打印并显示当前的MAINFEST.MF文件中的信息
		while (iterator.hasNext()) {
			Entry<Object, Object> next = iterator.next();
			Object key = next.getKey();
			Object value = next.getValue();
			// 这里可以获取到Class-Path,或者某个执行的Main-Class
			System.out.println(key + ": " + value);
		}
	}
}

处理方式和处理zip文件是一样的,执行的结果为:
在这里插入图片描述
读取到MANIFEST.MF文件和class文件,而且实例创建成功,注意需要URLClassLoader

3. JarInputStream方式


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

/**
 * 
 * @author hy
 * @createTime 2021-06-20 09:41:55
 * @description 读取jar的内容并获得解析(使用jarInputStream方式)
 *
 */
public class ReadJarTestUsingJarInputStream {
	public static void main(String[] args) throws MalformedURLException {
		String jarFilePath = "C:\\Users\\admin\\Desktop\\java的测试\\commons-test\\myCommons.jar";

		File file = new File(jarFilePath);

		if (!file.exists()) {
			System.out.println("文件不存在!");
			return;
		}
		if (!file.isFile()) {
			System.out.println("读取的为文件夹而非文件!");
			return;
		}
		if (!file.canRead()) {
			System.out.println("当前文件不可读!");
			return;
		}
		URL url1 = file.toURI().toURL();
		// 必须使用urlClassLoader,才能实例化当前加载的类
		URLClassLoader jarUrlClassLoader = new URLClassLoader(new URL[] { url1 },
				Thread.currentThread().getContextClassLoader());
		try (JarInputStream jis = new JarInputStream(new FileInputStream(file))) {
			Manifest manifest = jis.getManifest();
			pringManifestFile(manifest);
			JarEntry nextJarEntry = jis.getNextJarEntry();
			while (nextJarEntry != null) {
				String className = getClassName(nextJarEntry);
				if (className != null && className.endsWith("MySQLConnectionCliTest")) {
					loadAndInstanceClass(className, jarUrlClassLoader);
				}

				nextJarEntry = jis.getNextJarEntry();
			}
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	/**
	 * 
	 * @author hy
	 * @createTime 2021-06-20 10:31:25
	 * @description 加载类和实例化类
	 * @param clazzName
	 * @param classLoader
	 *
	 */
	private static void loadAndInstanceClass(String clazzName, ClassLoader classLoader) {
		try {
			// 需要使用其他的classLoader加载
			Class<?> forName = classLoader.loadClass(clazzName);
			System.out.println(forName);
			try {
				Object newInstance = forName.newInstance();
				System.out.println(newInstance);
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	private static String getClassName(JarEntry entry) {
		String name = entry.getName();
		// 这个获取的就是一个实体类class java.util.jar.JarFile$JarFileEntry
		// Class<? extends JarEntry> class1 = nextElement.getClass();
		System.out.println("entry name=" + name);
		// 加载某个class文件,并实现动态运行某个class
		if (name.endsWith(".class")) {
			String replace = name.replace(".class", "").replace("/", ".");
			return replace;
		}
		return null;
	}

	/**
	 * 
	 * @author hy
	 * @createTime 2021-06-20 10:32:16
	 * @description 输出当前的manifest文件中的信息内容
	 * @param manifest
	 *
	 */
	private static void pringManifestFile(Manifest manifest) {
		Attributes mainAttributes = manifest.getMainAttributes();
		Set<Entry<Object, Object>> entrySet = mainAttributes.entrySet();
		Iterator<Entry<Object, Object>> iterator = entrySet.iterator();
		// 打印并显示当前的MAINFEST.MF文件中的信息
		while (iterator.hasNext()) {
			Entry<Object, Object> next = iterator.next();
			Object key = next.getKey();
			Object value = next.getValue();
			// 这里可以获取到Class-Path,或者某个执行的Main-Class
			System.out.println(key + ": " + value);
		}
	}
}

执行结果为:

在这里插入图片描述
注意这里的JarInputStream是通过判断 jis.getNextJarEntry();并判断是否为null方式判断是否还有下一个元素

执行成功!

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值