http://yangzb.javaeye.com/blog/249819#comments
动态修改CLASSPATH
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Class to handle CLASSPATH construction
*/
public class Classpath {
Vector _elements = new Vector();
public Classpath() {}
public Classpath(String initial) {
addClasspath(initial);
}
public boolean addComponent(String component) {
if ((component != null) && (component.length() > 0)) {
try {
File f = new File(component);
if (f.exists()) {
File key = f.getCanonicalFile();
if (!_elements.contains(key)) {
_elements.add(key);
return true;
}
}
} catch (IOException e) {}
}
return false;
}
public boolean addComponent(File component) {
if (component != null) {
try {
if (component.exists()) {
File key = component.getCanonicalFile();
if (!_elements.contains(key)) {
_elements.add(key);
return true;
}
}
} catch (IOException e) {}
}
return false;
}
public boolean addClasspath(String s) {
boolean added = false;
if (s != null) {
StringTokenizer t = new StringTokenizer(s, File.pathSeparator);
while (t.hasMoreTokens()) {
added |= addComponent(t.nextToken());
}
}
return added;
}
public String toString() {
StringBuffer cp = new StringBuffer(1024);
int cnt = _elements.size();
if (cnt >= 1) {
cp.append(((File) (_elements.elementAt(0))).getPath());
}
for (int i = 1; i < cnt; i++) {
cp.append(File.pathSeparatorChar);
cp.append(((File) (_elements.elementAt(i))).getPath());
}
return cp.toString();
}
public URL[] getUrls() {
int cnt = _elements.size();
URL[] urls = new URL[cnt];
for (int i = 0; i < cnt; i++) {
try {
urls[i] = ((File) (_elements.elementAt(i))).toURL();
} catch (MalformedURLException e) {}
}
return urls;
}
public ClassLoader getClassLoader() {
URL[] urls = getUrls();
ClassLoader parent = Thread.currentThread().getContextClassLoader();
if (parent == null) {
parent = Classpath.class.getClassLoader();
}
if (parent == null) {
parent = ClassLoader.getSystemClassLoader();
}
return new URLClassLoader(urls, parent);
}
}
代码:
private Classpath classPath = new Classpath(System.getProperty("java.class.path"));
System.setProperty("java.class.path", classPath.toString());
ClassLoader classloader = classPath.getClassLoader();
Thread.currentThread().setContextClassLoader(classloader);
通过修改当前环境的ClassLoader来实现。
如何从ClassLoader中得到Classpath呢?
URL sour = Thread.currentThread().getContextClassLoader().getResource(".");
System.out.println(sour);
输出:file:/D:/workspace1/Pay-Plateform-ServiceEjb-Test/build/classes/
评论
Made In Zeal 转载请保留原始链接:http://www.zeali.net/entry/337
标签 ( Tags ): classpath , classloader , 源代码
对于Java开发人员(尤其是初学者)来说,因为classpath配置问题所导致的代码编译运行出错相当普遍,经验教训足可以专文叙之。实际上,我们可以通过实现自定义的ClassLoader等方法来尽量避免classpath对于系统环境的依赖。
通过加参数调用 javac,可以在编译时使用自定义的 ClassLoader 来完成类的定位加载:
javac -J-Djava.system.class.loader=my.ClassLoaderImpl theSource.java
自定义 ClassLoader 的方式可以参考这里(基本上来说就是通过继承 findClass(String) 方法来使JVM按照自己期望的规则来加载类)。还处于beta阶段的 Mustang Java SE 6 据说将提供新的工具 javax.tools.JavaCompilerTool 来替代 javac ,这个全新的编译工具应该会给程序员更好的编译体验。
大多数流行的 java IDE 都大大简化了对于 classpath 的配置过程,以至于很多在程序员的开发环境运行良好的代码发布之后才出现各种各样的问题。所以要想让程序包能够顺利的执行于产品环境,我们通常的做法是写一堆的 bat 或 shell 脚本来完成各种运行参数的配置。而这些大段大段的脚本当中,对 classpath 的配置占了相当大的比重。
因此 Heikki Uusitalo 写了一个 BootLoader 类(原始代码似乎有些问题,这里修改了一下):将这个类作为引导程序去根据自定义的规则来加载所有必需的 jar 包等资源,然后再启动真正的 main 方法。把这个 BootLoader 类单独打包成一个 jar 文件,运行的时候只需要运行它即可。当然你可以根据实际情况修改读取的路径、规则等信息。
view plainprint?
1. import java.io.*;
2. import java.net.*;
3. import java.lang.reflect.*;
4.
5. public class BootLoader
6. {
7. public static void main(final String[] args) throws Exception
8. {
9. // check that the lib folder exists
10. File libRoot = new File(LIB_FOLDER);
11. if(!libRoot.exists()) {
12. throw new Exception("No 'lib' folder exists!");
13. }
14. // read all *.jar files in the lib folder to array
15. File[] libs = libRoot.listFiles(new FileFilter()
16. {
17. public boolean accept(File dir)
18. {
19. String name = dir.getName().toLowerCase();
20. return name.endsWith("jar") || name.endsWith("zip");
21. }
22. });
23.
24. URL[] urls = new URL[libs.length];
25. // fill the urls array with URLs to library files found in libRoot
26. for(int i = 0; i < libs.length; i++) {
27. urls[i] = new URL("file",null,libs[i].getAbsolutePath());
28. }
29. // create a new classloader and use it to load our app.
30. classLoader = new URLClassLoader(urls,
31. Thread.currentThread().
32. getContextClassLoader());
33. // get the main method in our application to bring up the app.
34. final Method mtd = classLoader.loadClass(APP_MAIN_CLASS).getMethod("main",
35. new Class[] {String[].class});
36. // Using thread to launch the main 'loop' so that the current Main method
37. // can return while the app is starting
38. new Thread(new Runnable()
39. {
40. public void run()
41. {
42. try {
43. mtd.invoke(null,new Object[] {args});
44. } // forward the args
45. catch(Exception e) {
46. throw new RuntimeException(e);
47. }
48. }
49. },"AppMain").start();
50. // Give the app some time to start before returning from main.
51. // This doesn't delay the starting in any way
52. Thread.sleep(1000);
53. }
54.
55. private static final String LIB_FOLDER = "lib";
56. private static final String APP_MAIN_CLASS = "com.my.application.MyTest";
57. private static ClassLoader classLoader;
58. }