Java加载jar文件并调用jar文件当中有参数和返回值的方法

在工作当中经常遇到反编译后的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  */ 

程序运行的结果:

 

转载于:https://www.cnblogs.com/songshu120/p/6135285.html

在jdk1.2以后,类加载是通过委托来完成的,这意味着如果 ClassLoader 不能找到类,它会请求父代 ClassLoader 来执行此项任务,所有 ClassLoaders 的根是系统 ClassLoader,它会以缺省方式装入类 -- 即,从本地文件系统。今天我们就来探讨一下在jvm中这些机制是怎样运行的。让我们假设有一个class字节码文件(比如Hello.class文件),那么在应用程序中,他是如何被加载进来,并形成一个类对象的呢?我们这篇文章的目的就是为了解释这个问题。 在java.lang包里有个ClassLoader类,ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。其中有个loadClass(String name, boolean resolve)方法,该方法为ClassLoader的入口点,在jdk1.2以后,loadClass方法将缺省调用findClass方法,详细内容可以参考API文档,我们编写的ClassLoader主要就是为了覆盖以上两个方法。回到我们刚才的问题,怎样读进字节码文件,并把它构成一个类对象呢?在ClassLoader里有个方法,Class defineClass(String name, byte[] b, int off, int len),答案就在这里了,我们根据把class字节码文件(如Hello.class)读进一个字节数组里,byte[] b,并把它转化为Class对象,而这些数据可以来源于文件,网络等,神奇吧:) defineClass管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成最终的。 其他一些方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值