`
chenzehe
  • 浏览: 532766 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

用反射解析jar文件并执行里面Java代码

阅读更多

1、使用JarFile类读取jar包MANIFEST.MF中的Main-Class,如果没有设置Main-Class则调用方法中指定执行函数

2、解压jar文件

3、设置classPath

4、利用反射取得class和method,并运行该method

如下代码Run.java将被打包到jar文件中,使用Maven构建并打包:

 

package com.chenzehe.runjar;
public class Run {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("run......");
		if (args.length > 0) {
			System.out.println("args: " + args[0]);
		}
	}
}

 

开始打包没有指定在MANIFEST.MF中指定Main-Class,下面运行时只能指定要运行的类。

 RunJar.java为解析并执行该jar文件方法的类:

 

package com.chenzehe.runjar;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

public class RunJar {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Throwable {
		String usage = "RunJar jarFile [mainClass] args...";

		if (args.length < 1) {
			System.err.println(usage);
			System.exit(-1);
		}
		int firstArg = 0;
		String fileName = args[firstArg++];
		File file = new File(fileName);

		// 从jar文件MANIFEST.MF中读取Main-Class
		String mainClassName = null;
		JarFile jarFile;
		try {
			jarFile = new JarFile(fileName);
		} catch (IOException io) {
			throw new IOException("Error opening job jar: " + fileName)
					.initCause(io);
		}

		Manifest manifest = jarFile.getManifest();
		if (manifest != null) {
			mainClassName = manifest.getMainAttributes().getValue("Main-Class");
		}
		jarFile.close();

		if (mainClassName == null) {
			if (args.length < 2) {
				System.err.println(usage);
				System.exit(-1);
			}
			// 如果MANIFEST.MF未设置Main-Class,则用户输入
			mainClassName = args[firstArg++];
		}
		mainClassName = mainClassName.replaceAll("/", ".");
		final File workDir = File.createTempFile("unjar", "",
				new File(System.getProperty("user.dir")));
		workDir.delete();
		workDir.mkdirs();
		if (!workDir.isDirectory()) {
			System.err.println("Mkdirs failed to create " + workDir);
			System.exit(-1);
		}

		// 解压jar文件
		unJar(file, workDir);

		// 设置classPath
		ArrayList<URL> classPath = new ArrayList<URL>();
		classPath.add(new File(workDir + "/").toURL());
		classPath.add(file.toURL());
		ClassLoader loader = new URLClassLoader(classPath.toArray(new URL[0]));
		Thread.currentThread().setContextClassLoader(loader);

		// 利用反射取得class和method
		Class<?> mainClass = Class.forName(mainClassName, true, loader);
		Method main = mainClass.getMethod("main", new Class[] { Array
				.newInstance(String.class, 0).getClass() });
		String[] newArgs = Arrays.asList(args).subList(firstArg, args.length)
				.toArray(new String[0]);
		try {
			// 运行方法
			main.invoke(null, new Object[] { newArgs });
		} catch (InvocationTargetException e) {
			throw e.getTargetException();
		}
	}
        //解压jar包中的文件到toDir目录
	public static void unJar(File jarFile, File toDir) throws IOException {
		JarFile jar = new JarFile(jarFile);
		try {
			Enumeration entries = jar.entries();
			while (entries.hasMoreElements()) {
				JarEntry entry = (JarEntry) entries.nextElement();
				if (!entry.isDirectory()) {
					InputStream in = jar.getInputStream(entry);
					try {
						File file = new File(toDir, entry.getName());
						if (!file.getParentFile().mkdirs()) {
							if (!file.getParentFile().isDirectory()) {
								throw new IOException(
										"Mkdirs failed to create "
												+ file.getParentFile()
														.toString());
							}
						}
						OutputStream out = new FileOutputStream(file);
						try {
							byte[] buffer = new byte[8192];
							int i;
							while ((i = in.read(buffer)) != -1) {
								out.write(buffer, 0, i);
							}
						} finally {
							out.close();
						}
					} finally {
						in.close();
					}
				}
			}
		} finally {
			jar.close();
		}
	}
}

 

该代码为Hadoop中job提交到服务器调用的代码RunJar。

下载本例代码

 

 

 

0
0
分享到:
评论

相关推荐

    apache-commons源码及jar文件

    Commons-Digester 是一个 XML-Java对象的映射工具,用于解析 XML配置文件. Discovery Commons-Discovery 提供工具来定位资源 (包括类) ,通过使用各种模式来映射服务/引用名称和资源名称。. EL Commons-EL 提供在...

    java jdk实列宝典 光盘源代码

    12反射 是java程序开发的特征之一,允许java程序对自身进行检查,并能直接操作程序的内部属性; instanceof操作符,instanceof.java; 获取类的信息,ViewClassInfoJrame.java; 动态调用类的方法,CallMetod.java; ...

    JAVA_API1.6文档(中文)

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    Java 1.6 API 中文 New

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    java api最新7.0

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    JavaAPI1.6中文chm文档 part1

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    框架中常用的jar包作用

    Digester基于规则的XML文档解析,主要用于XML到Java对象的映射. commons-beanutils.jar 提供对Java 反射和自省API的包装. aspectjweaver.jar 用于在Spring 2.0中集成AspectJ AspectJ LTW织入器 ognl.jar OGNL是...

    JAVA 范例大全 光盘 资源

    JAVA 范例大全 光盘 资源 书籍目录: 前言. 第1章 开发环境搭建 1 实例1 下载、安装并配置JDK 1 实例2 第一个Java程序 3 实例3 在Eclipse中创建第一个Java程序 4 常见问题 javac不是内部或者外部命令 6 常见...

    JavaAPI中文chm文档 part2

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    比较全面的:Jakarta-commons jar包(附: chm参考手册 & 资源简介)

    commons-jelly 能够把XML转换成可执行代码,所以Jelly是一个基于XML与Java的脚本和处理引擎 commons-jexl 是一个表达式语言,通过借鉴来自于Velocity的经验扩展了JSTL定义的表达式语言 commons-jxpath 定义了一个...

    Java JDK实例宝典

    全部代码出自电子工业出版社夏先波的《Java JDK实例宝典》一书,本书以J2SE 5.0为开发环境,选取Java应用的典型实例,循序渐进地介绍了Java语言的各种开发方法和技巧,实例代码注释详细规范,思路清晰。 第1章 ...

    java jdk-api-1.6 中文 chmd

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    Android代码-JsonLube

    JsonLube用于将Json对象转成JAVA Bean对象,不同于传统在运行时进行反射的方式,JsonLube采用在编译时自动生成解析Json的代码,使用方式依然简单,然而在移动平台上却可以收获更好的性能。 使用方式 gradle配置 ...

    将 Flex 集成到 Java EE 应用程序的最佳实践(完整源代码)

    尽管现有的 EmployeeMgmt 应用程序已经有了 Façade 接口,但这个接口是暴露给 Servlet 使用的,最好能再为 Flex 定义另一个接口 FlexService,并隐藏 Java 语言的特定对象(如 清单 1 所示): 清单 1. Flex...

    [Java参考文档]

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    sarras:通过Java应用程序的静态和动态分析为Graal基板VM反射配置文件生成器

    解析给定jar中所有类的字节码,自省反射调用(通过反射访问类/方法/字段等),并将其配置添加到生成的反射配置文件中。 动态剖析 作为Java代理附加到常规Java应用程序(不是来自本机映像),并拦截反射调用(还包括...

Global site tag (gtag.js) - Google Analytics