转载文章:Java加载jar文件并调用jar文件当中有参数和返回值的方法 - 小淞鼠 - 博客园
在工作当中经常遇到反编译后的jar文件,并要传入参数了解其中的某些方法的输出,想到Java里面的反射可以实现加载jar文件并调用其中的方法来达到自己的目的。就写了个Demo代码。
经过项目实践,此方法会导致oom,解决办法是增加一个map缓存与调高jvm内存参数。但这也只是临时过渡办法,不能作为公司生产使用。使用场景结合自己情况!!!
解决方法链接:java 反射引起的内存溢出_清风徐来#¥%……的博客-CSDN博客_java反射内存溢出
以下的类可以编译生成hello.jar文件。
package org.lele.fatpanda;
public class Util
{
public static String myName;
/*
* 无参数,无返回值的方法。
*/
public static void getVersion()
{
System.out.println("java version: " + System.getProperty("java.version") );
}
/*
*有参数,无返回值的方法。
*/
public static void setTmpName(String name)
{
myName = name;
System.out.println("Set Tmp Name Succeed and the name is : " + myName);
}
/*
* 单个参数,有返回值的方法。
*/
public static String getName(String prefix)
{
return prefix + "lele";
}
/*
* 多个参数,有返回值的方法。
*/
public static String test(String i1, int i2)
{
return i1 + i2;
}
}
/*
* 一个生成jar文件的类文件,要使用public的访问权限,如果在方便进行反射调用,则要将方法声明为static。
*/
下面的就是实现动态加载并调用的主要代码。
package com.xiyoulele.wh;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class Main
{
public static void main(String[] args)
{
URL[] urls = new URL[] {};
MyClassLoader classLoader = new MyClassLoader(urls, null); //自定义ClassLoader来加载jar文件
try
{
classLoader.addJar(new File("c:\\hello.jar").toURI().toURL()); //加载特定路径的jar文件
Class<?> clazz = classLoader.loadClass("org.lele.fatpanda.Util"); //动态加载jar文件当中的特定类的class文件
//传入一个参数一个返回值
Class<?>[] typeA = new Class[1]; //传入要调用的方法的参数类型
typeA[0] = String.class;
Object[] objsA = new Object[1]; //传入要调用的方法的具体参数
objsA[0] = new String("xiyou");
Method method = clazz.getMethod("getName", typeA); //获取要被调用的特定方法 getName(String xx)
String result = method.invoke(clazz, objsA).toString(); //调用方法,获取方法的返回值。
System.out.println(result); //输出方法
//传入2个参数一个人返回值
Class<?>[] typesB = new Class[2];
typesB[0] = String.class;
typesB[1] = Integer.TYPE;
Object[] ObjsB = new Object[2];
ObjsB[0] = new String("ZT");
ObjsB[1] = new Integer(520);
Method newMethod = clazz.getMethod("test", typesB);
String res = newMethod.invoke(clazz.newInstance(), ObjsB).toString();
System.out.println(res);
//有传入的参数,没有返回值
Class<?>[] typesC = new Class[1];
typesC[0] = String.class;
Object[] objsC = new Object[1];
objsC[0] = new String("xiyoulele");
Method methodC = clazz.getMethod("setTmpName", typesC);
methodC.invoke(clazz.newInstance(), objsC);
//无参数,无返回值
Method methodD = clazz.getDeclaredMethod("getVersion");
methodD.invoke(clazz.newInstance());
classLoader.close(); //关闭类的加载器
} catch (Exception e)
{
e.printStackTrace();
}
}
//继承URLClassLoader来实现对jar文件的加载
static class MyClassLoader extends URLClassLoader
{
public MyClassLoader(URL[] urls)
{
super(urls);
}
public MyClassLoader(URL[] urls, ClassLoader parent)
{
super(urls, parent);
}
public void addJar(URL url)
{
this.addURL(url);
}
}
}
/*
* 需求:加载jar文件,动态调用里面的方法,该方法带有参数和返回值。
*/
程序运行的结果: