JAVA实现动态加载jar包并调用其中的方法

一、首先我们编写一个需要达成jar包的测试类,代码如下所示
package com.test.demo;
public class Demo2 {
	public  String getHello(String str){
		return "hello:"+str;
	}
	public String getHello1(String str){
		return "hello1:"+str;
	}
}

测试代码中包含了两个方法,getHello,getHello1里面方法均需要传入参数,并且均有返回值


如图所示,我们将上述的代码打包成为一个名为Demo2.jar的文件,然后我们将这个文件在需要调用的工程的目录中,本示例中我是讲起加在了工程的lib目录中,注意此处并不需要build path进入工程,只需要将文件拷贝在你想要的目录中

String jar_path="file:./lib/Demo2.jar";
String class_path="com.test.demo.Demo2";
然后我们新建一个类用来测试调用jar包,在代码中我们声明了两个变量,分别是jar文件的路径,(此处为文件类型的路径即以file:开头,接下来的文件路径可以是相对路径也可以是绝对路径),还有一个class所在的路径,需要带包名,如果在default包中则直接为类名即可(个人建议不要使用default包,容易出各种想象不到的问题)

ClassLoader cl = new URLClassLoader(new URL[]{ new URL(jar_path)});//从jar包中加载类加载器
Class<?> c = cl.loadClass(class_path);//从类加载器中加载类
Method[] methods = c.getDeclaredMethods();//从类中加载方法
method.invoke(c.newInstance(),"1");//调用类中的方法,此处需要注意当jar包中方法不是static方法时,需要使用c.newInstance()方法实例化一个对象出来

下面上完整代码

package com.test.demo;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class DemoMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String jar_path="file:./lib/Demo2.jar";
		String class_path="com.test.demo.Demo2";
		try {
			ClassLoader cl = new URLClassLoader(new URL[]{ new URL(jar_path)});
			Class<?> c = cl.loadClass(class_path);
			Method[] methods = c.getDeclaredMethods();
			for(Method method:methods){
				System.out.println(method.getName());
				System.out.println(method.invoke(c.newInstance(),"1"));
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
运行结果如下所示:

getHello
hello:1
getHello1
hello1:1




在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
发出的红包

打赏作者

L若儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值