动态加载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

 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

 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(nullnew 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

测试时运行这个命令
java -Duser.class.pool=c:\ -Djava.system.class.loader=ConfigurableClassLoader TestMyClassLoader




posted on 2008-06-09 16:58  逍遥子  阅读(616)  评论(0编辑  收藏  举报

导航