运行期加载额外的jar包或者class
有时候我们在程序已经运行了以后,还是想要再额外的去加载一些jar或类,需要怎么 做呢? 简单说就是不使用命令行参数的情况下,怎么用代码来运行时改变加载类的路径和方式。
实现方式:在当前 的应用类加载器里,使用
URLClassLoader
类的方法addURL
,不过该方法是protected
的,需要反射处理一 下,因为程序在启动时并没有显示加载HelloByteCode
类,所以在添加完了classpath
以后,没法直接显式初始化,需要使用Class.forName
的方式来拿到已经加载的HelloByteCode
类 (Class.forName(“demo.jvm0104.HelloByteCode”)默认会初始化
(一)背景-需求
- 运行时动态添加额外的jar或类。例如添加本地
C:\Users\起凤\Desktop\temp\demo\jvm0104
下的HelloByteCode.class
package demo.jvm0104;
public class HelloByteCode {
public static void main(String[] args) {
HelloByteCode obj = new HelloByteCode();
System.out.println("Hello World[你好,世界]!");
}
}
(二)具体实现代码
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* 运行期加载额外的jar包或者class
*
* @author 起凤
* @description: TODO
* @date 2022/3/1
*/
public class JvmAppClassLoaderAddURL {
public static void main(String[] args) {
// 需要加上 file: 否则会报 unknown protocol: 错误
String appPath = "file:///C:/Users/起凤/Desktop/temp/";
URLClassLoader urlClassLoader = (URLClassLoader) JvmAppClassLoaderAddURL.class.getClassLoader();
try {
Method addUrl = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addUrl.setAccessible(true);
URL url = new URL(appPath);
addUrl.invoke(urlClassLoader, url);
/// forName 入参是包路径必须要是类全限定名,强制初始化类
Class<?> aClass = Class.forName("demo.jvm0104.HelloByteCode");
Object instance = aClass.newInstance();
Method main = aClass.getMethod("main", String[].class);
main.invoke(null,(Object) null);
} catch (Exception e) {
e.printStackTrace();
}
}
}