动态加载Java运行环境和运行实例
最近想做一个Java软件,可以动态的增加插件。插件的数据、资源和软件全部在插件内部。增加插件时,不需要对原有的软件进行新的配置和修改。实现方法并不复杂,插件的一个配置文件中配置了,这个插件的定义、参数和软件的调入口。然后软件运行时,对插件文件夹进行扫描,如果发现新插件,那么就将这个插件加载到软件中。通过动态加载类的方式可以调用这个插件。
但是存在一个问题是,如何将这些java资源加载到java运行环境中?
后来在网上发现有两种方法,一种是通过反射机制对系统运行的ClassLoader进行操作,向其中添加运行环境。因为这个方法是protected,无法调用,所以只能通过反射机制来处理。另一种方法是通过改写ClassLoader,来加载自己的环境,然后在运行java时,通过参数-Djava.system.class.loader=XXXX来使用自己的类加载器。
下面是两个例子:
1
/*
2
* HelloWorld.java
3
* 编译完之后,将其class文件放到C盘下
4
*/
5
public class HelloWorld {
6
7
public void print(String s) {
8
System.out.println("HelloWorld");
9
}
10
}
11
12
/*2
* HelloWorld.java3
* 编译完之后,将其class文件放到C盘下 4
*/ 5
public class HelloWorld {6

7
public void print(String s) {8
System.out.println("HelloWorld");9
}10
}11

12

1
/*
2
* PackageManager.java
3
* 动态向系统类加载器中添加新环境
4
*/
5
import java.io.File;
6
import java.lang.reflect.Method;
7
import java.net.URL;
8
import java.net.URLClassLoader;
9
import java.util.StringTokenizer;
10
11
public 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
*/
48
public 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.java3
* 动态向系统类加载器中添加新环境 4
*/5
import java.io.File;6
import java.lang.reflect.Method;7
import java.net.URL;8
import java.net.URLClassLoader;9
import java.util.StringTokenizer;10

11
public 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
*/48
public 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
8
import java.io.File;
9
import java.lang.reflect.InvocationTargetException;
10
import java.lang.reflect.Method;
11
import java.net.MalformedURLException;
12
import java.net.URL;
13
import java.net.URLClassLoader;
14
15
public 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
* ConfigurableClassLoader3
* 改写ClassLoader类4
* 这个好处在于,可以将所有的运行时问题,全部在程序中动态加载5
* 从而,不需要编写复杂的Java运行环境批处理文件6
*/7

8
import java.io.File;9
import java.lang.reflect.InvocationTargetException;10
import java.lang.reflect.Method;11
import java.net.MalformedURLException;12
import java.net.URL;13
import java.net.URLClassLoader;14

15
public 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
else29
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, InvocationTargetException44
{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
*/
4
import java.lang.reflect.Method;
5
import java.net.URLClassLoader;
6
7
public class TestMyClassLoader {
8
9
public 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
*/4
import java.lang.reflect.Method;5
import java.net.URLClassLoader;6

7
public class TestMyClassLoader {8

9
public static void main(String[] args) {10
try {11
URLClassLoader sysloader = (URLClassLoader) ClassLoader12
.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



浙公网安备 33010602011771号