在工作当中经常遇到反编译后的jar文件,并要传入参数了解其中的某些方法的输出,想到Java里面的反射可以实现加载jar文件并调用其中的方法来达到自己的目的。就写了个Demo代码。
以下的类可以编译生成hello.jar文件。
1 package org.lele.fatpanda;
2
3 public class Util
4 {
5 public static String myName;
6 /*
7 * 无参数,无返回值的方法。
8 */
9 public static void getVersion()
10 {
11 System.out.println("java version: " + System.getProperty("java.version") );
12 }
13 /*
14 *有参数,无返回值的方法。
15 */
16 public static void setTmpName(String name)
17 {
18 myName = name;
19 System.out.println("Set Tmp Name Succeed and the name is : " + myName);
20 }
21 /*
22 * 单个参数,有返回值的方法。
23 */
24 public static String getName(String prefix)
25 {
26 return prefix + "lele";
27 }
28 /*
29 * 多个参数,有返回值的方法。
30 */
31 public static String test(String i1, int i2)
32 {
33 return i1 + i2;
34 }
35
36 }
37 /*
38 * 一个生成jar文件的类文件,要使用public的访问权限,如果在方便进行反射调用,则要将方法声明为static。
39 */
下面的就是实现动态加载并调用的主要代码。
1 package com.xiyoulele.wh;
2
3 import java.io.File;
4 import java.lang.reflect.Method;
5 import java.net.URL;
6 import java.net.URLClassLoader;
7
8 public class Main
9 {
10 public static void main(String[] args)
11 {
12 URL[] urls = new URL[] {};
13 MyClassLoader classLoader = new MyClassLoader(urls, null); //自定义ClassLoader来加载jar文件
14
15 try
16 {
17 classLoader.addJar(new File("c:\\hello.jar").toURI().toURL()); //加载特定路径的jar文件
18 Class<?> clazz = classLoader.loadClass("org.lele.fatpanda.Util"); //动态加载jar文件当中的特定类的class文件
19
20 //传入一个参数一个返回值
21
22 Class<?>[] typeA = new Class[1]; //传入要调用的方法的参数类型
23 typeA[0] = String.class;
24
25 Object[] objsA = new Object[1]; //传入要调用的方法的具体参数
26 objsA[0] = new String("xiyou");
27
28 Method method = clazz.getMethod("getName", typeA); //获取要被调用的特定方法 getName(String xx)
29
30 String result = method.invoke(clazz, objsA).toString(); //调用方法,获取方法的返回值。
31
32 System.out.println(result); //输出方法
33
34 //传入2个参数一个人返回值
35
36 Class<?>[] typesB = new Class[2];
37 typesB[0] = String.class;
38 typesB[1] = Integer.TYPE;
39
40 Object[] ObjsB = new Object[2];
41 ObjsB[0] = new String("ZT");
42 ObjsB[1] = new Integer(520);
43
44 Method newMethod = clazz.getMethod("test", typesB);
45 String res = newMethod.invoke(clazz.newInstance(), ObjsB).toString();
46
47 System.out.println(res);
48
49 //有传入的参数,没有返回值
50 Class<?>[] typesC = new Class[1];
51 typesC[0] = String.class;
52
53 Object[] objsC = new Object[1];
54 objsC[0] = new String("xiyoulele");
55
56 Method methodC = clazz.getMethod("setTmpName", typesC);
57 methodC.invoke(clazz.newInstance(), objsC);
58
59 //无参数,无返回值
60 Method methodD = clazz.getDeclaredMethod("getVersion");
61 methodD.invoke(clazz.newInstance());
62
63 classLoader.close(); //关闭类的加载器
64
65 } catch (Exception e)
66 {
67 e.printStackTrace();
68 }
69 }
70 //继承URLClassLoader来实现对jar文件的加载
71 static class MyClassLoader extends URLClassLoader
72 {
73 public MyClassLoader(URL[] urls)
74 {
75 super(urls);
76 }
77 public MyClassLoader(URL[] urls, ClassLoader parent)
78 {
79 super(urls, parent);
80 }
81 public void addJar(URL url)
82 {
83 this.addURL(url);
84 }
85 }
86 }
87 /*
88 * 需求:加载jar文件,动态调用里面的方法,该方法带有参数和返回值。
89 */
程序运行的结果: