动态加载Java运行环境和运行实例
最近想做一个Java软件,可以动态的增加插件。插件的数据、资源和软件全部在插件内部。增加插件时,不需要对原有的软件进行新的配置和修改。实现方法并不复杂,插件的一个配置文件中配置了,这个插件的定义、参数和软件的调入口。然后软件运行时,对插件文件夹进行扫描,如果发现新插件,那么就将这个插件加载到软件中。通过动态加载类的方式可以调用这个插件。
但是存在一个问题是,如何将这些java资源加载到java运行环境中?
后来在网上发现有两种方法,一种是通过反射机制对系统运行的ClassLoader进行操作,向其中添加运行环境。因为这个方法是protected,无法调用,所以只能通过反射机制来处理。另一种方法是通过改写ClassLoader,来加载自己的环境,然后在运行java时,通过参数-Djava.system.class.loader=XXXX来使用自己的类加载器。
下面是两个例子:
1/*
2* HelloWorld.java
3* 编译完之后,将其class文件放到C盘下
4*/
5public class HelloWorld {
6
7public void print(String s) {
8 System.out.println("HelloWorld");
9}
10}
11
12
2* HelloWorld.java
3* 编译完之后,将其class文件放到C盘下
4*/
5public class HelloWorld {
6
7public void print(String s) {
8 System.out.println("HelloWorld");
9}
10}
11
12
1/*
2* PackageManager.java
3* 动态向系统类加载器中添加新环境
4*/
5import java.io.File;
6import java.lang.reflect.Method;
7import java.net.URL;
8import java.net.URLClassLoader;
9import java.util.StringTokenizer;
10
11public class PackageManager {
12 public static final String CLASS_PATH = "classpath";
13 static URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
14 static Class sysclass = URLClassLoader.class;
15 static Method method;
16
17 public static void importClasspath() {
18 try {
19 StringTokenizer st = new StringTokenizer(System.getenv(CLASS_PATH), ";");
20 while(st.hasMoreTokens())
21 addURL(st.nextToken());
22 } catch(Exception ex) { ex.printStackTrace(); }
23 }
24
25 public static void addURL(String path) {
26 try {
27 addURL((new File(path)).toURL());
28 } catch(Exception ex) { ex.printStackTrace(); }
29 }
30
31 public static void addURL(URL u) {
32 try {
33 if(method == null) {
34 Class[] cs = new Class[] {URL.class};
35 method = sysclass.getDeclaredMethod("addURL", cs);
36 method.setAccessible(true);
37 }
38 method.invoke(sysloader,new Object[]{ u });
39 } catch (Exception ex) {
40 ex.printStackTrace();
41 //throw new IOException("Error, could not add URL to system classloader");
42 }
43 }
44
45/**
46* 动态加载环境和动态加载类方法
47*/
48public static void main(String[] args) {
49 // importClasspath();
50 addURL("C:\\");
51 try {
52 Class c = sysloader.loadClass("HelloWorld");
53 Method main = c.getDeclaredMethod("print",
54 new Class[] { String.class });
55
56 if (main == null) {
57 System.out.println("main is null");
58 } else {
59 main.invoke(c.newInstance(), new Object[] { "s" });
60 }
61
62 } catch (Exception e) {
63 e.printStackTrace();
64 }
65 }
66}
67
68
2* PackageManager.java
3* 动态向系统类加载器中添加新环境
4*/
5import java.io.File;
6import java.lang.reflect.Method;
7import java.net.URL;
8import java.net.URLClassLoader;
9import java.util.StringTokenizer;
10
11public class PackageManager {
12 public static final String CLASS_PATH = "classpath";
13 static URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
14 static Class sysclass = URLClassLoader.class;
15 static Method method;
16
17 public static void importClasspath() {
18 try {
19 StringTokenizer st = new StringTokenizer(System.getenv(CLASS_PATH), ";");
20 while(st.hasMoreTokens())
21 addURL(st.nextToken());
22 } catch(Exception ex) { ex.printStackTrace(); }
23 }
24
25 public static void addURL(String path) {
26 try {
27 addURL((new File(path)).toURL());
28 } catch(Exception ex) { ex.printStackTrace(); }
29 }
30
31 public static void addURL(URL u) {
32 try {
33 if(method == null) {
34 Class[] cs = new Class[] {URL.class};
35 method = sysclass.getDeclaredMethod("addURL", cs);
36 method.setAccessible(true);
37 }
38 method.invoke(sysloader,new Object[]{ u });
39 } catch (Exception ex) {
40 ex.printStackTrace();
41 //throw new IOException("Error, could not add URL to system classloader");
42 }
43 }
44
45/**
46* 动态加载环境和动态加载类方法
47*/
48public static void main(String[] args) {
49 // importClasspath();
50 addURL("C:\\");
51 try {
52 Class c = sysloader.loadClass("HelloWorld");
53 Method main = c.getDeclaredMethod("print",
54 new Class[] { String.class });
55
56 if (main == null) {
57 System.out.println("main is null");
58 } else {
59 main.invoke(c.newInstance(), new Object[] { "s" });
60 }
61
62 } catch (Exception e) {
63 e.printStackTrace();
64 }
65 }
66}
67
68
1/**
2* ConfigurableClassLoader
3* 改写ClassLoader类
4* 这个好处在于,可以将所有的运行时问题,全部在程序中动态加载
5* 从而,不需要编写复杂的Java运行环境批处理文件
6*/
7
8import java.io.File;
9import java.lang.reflect.InvocationTargetException;
10import java.lang.reflect.Method;
11import java.net.MalformedURLException;
12import java.net.URL;
13import java.net.URLClassLoader;
14
15public class ConfigurableClassLoader extends URLClassLoader {
16 public ConfigurableClassLoader(ClassLoader parent)
17 {
18 super(new URL[0], parent);
19
20 String property = System.getProperty("user.class.pool");
21
22 if (property != null) {
23 String[] paths = property.split(File.pathSeparator);
24 for (int i = 0; i < paths.length; ++i) {
25 try {
26 if (paths[i].startsWith("http:") || paths[i].startsWith("file:"))
27 addURL(new URL(paths[i]));
28 else
29 addURL(new File(paths[i]).toURL());
30 }
31 catch (MalformedURLException e) {
32 e.printStackTrace();
33 }
34 }
35 }
36 }
37
38 protected void addURL(URL url)
39 {
40 super.addURL(url);
41 }
42
43 public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
44 {
45 Class mainClass = Class.forName(args[0], false, ClassLoader.getSystemClassLoader());
46 Method entryMethod = mainClass.getMethod("main", new Class[] {String[].class});
47 String[] appArgs = new String[args.length - 1];
48 System.arraycopy(args, 1, appArgs, 0, appArgs.length);
49 entryMethod.invoke(null, new Object[] {appArgs});
50 }
51}
52
53
2* ConfigurableClassLoader
3* 改写ClassLoader类
4* 这个好处在于,可以将所有的运行时问题,全部在程序中动态加载
5* 从而,不需要编写复杂的Java运行环境批处理文件
6*/
7
8import java.io.File;
9import java.lang.reflect.InvocationTargetException;
10import java.lang.reflect.Method;
11import java.net.MalformedURLException;
12import java.net.URL;
13import java.net.URLClassLoader;
14
15public class ConfigurableClassLoader extends URLClassLoader {
16 public ConfigurableClassLoader(ClassLoader parent)
17 {
18 super(new URL[0], parent);
19
20 String property = System.getProperty("user.class.pool");
21
22 if (property != null) {
23 String[] paths = property.split(File.pathSeparator);
24 for (int i = 0; i < paths.length; ++i) {
25 try {
26 if (paths[i].startsWith("http:") || paths[i].startsWith("file:"))
27 addURL(new URL(paths[i]));
28 else
29 addURL(new File(paths[i]).toURL());
30 }
31 catch (MalformedURLException e) {
32 e.printStackTrace();
33 }
34 }
35 }
36 }
37
38 protected void addURL(URL url)
39 {
40 super.addURL(url);
41 }
42
43 public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
44 {
45 Class mainClass = Class.forName(args[0], false, ClassLoader.getSystemClassLoader());
46 Method entryMethod = mainClass.getMethod("main", new Class[] {String[].class});
47 String[] appArgs = new String[args.length - 1];
48 System.arraycopy(args, 1, appArgs, 0, appArgs.length);
49 entryMethod.invoke(null, new Object[] {appArgs});
50 }
51}
52
53
1/**
2* 这是对改写ClassLoader的测试方法
3*/
4import java.lang.reflect.Method;
5import java.net.URLClassLoader;
6
7public class TestMyClassLoader {
8
9public static void main(String[] args) {
10 try {
11 URLClassLoader sysloader = (URLClassLoader) ClassLoader
12 .getSystemClassLoader();
13 Class c = sysloader.loadClass("HelloWorld");
14 Method main = c.getDeclaredMethod("print",
15 new Class[] { String.class });
16
17 if (main == null) {
18 System.out.println("main is null");
19 } else {
20 main.invoke(c.newInstance(), new Object[] { "s" });
21 }
22
23 } catch (Exception e) {
24 e.printStackTrace();
25 }
26 }
27}
28
29
2* 这是对改写ClassLoader的测试方法
3*/
4import java.lang.reflect.Method;
5import java.net.URLClassLoader;
6
7public class TestMyClassLoader {
8
9public static void main(String[] args) {
10 try {
11 URLClassLoader sysloader = (URLClassLoader) ClassLoader
12 .getSystemClassLoader();
13 Class c = sysloader.loadClass("HelloWorld");
14 Method main = c.getDeclaredMethod("print",
15 new Class[] { String.class });
16
17 if (main == null) {
18 System.out.println("main is null");
19 } else {
20 main.invoke(c.newInstance(), new Object[] { "s" });
21 }
22
23 } catch (Exception e) {
24 e.printStackTrace();
25 }
26 }
27}
28
29
测试时运行这个命令
java -Duser.class.pool=c:\ -Djava.system.class.loader=ConfigurableClassLoader TestMyClassLoader