是否有可能在Java中dynamic添加到类path中?

java -classpath ../classes;../jar;. parserTester 

我怎样才能以编程方式获得上述命令的function? 喜欢,是否有可能运行如下:

 java parserTester 

并得到相同的结果? 我尝试使用URLClassLoader,但它修改了类path,并没有添加到它。

感谢名单!


感谢Milhous的回应。 但是,这就是我正在做的事情..怎样才能将jar放入classpath中? 我也尝试使用自定义类加载器:(

这工作..但不幸的是,我只需要运行它:java parserTester我想知道如果这样的事情是可能的?

它需要如此bcoz我有parserTester.java和.class在一个单独的文件夹。 我需要保留文件结构。 parserTester使用单独的jar文件夹中的jar。

您可以使用java.net.URLClassLoader来加载您想要的任何程序定义的URL列表的类:

公共类URLClassLoader扩展SecureClassLoader

这个类加载器用于从指向JAR文件和目录的URL的searchpath加载类和资源。 任何以“/”结尾的URL都被认为是指向一个目录。 否则,假定该URL是指将根据需要打开的JAR文件。

随后加载类和资源时将使用创buildURLClassLoader实例的线程的AccessControlContext。

加载的类默认授予权限,只能访问创buildURLClassLoader时指定的URL。

由于:1.2

而一些奇特的步法可以扩展它以支持使用通配符path名来拾取整个JAR目录(这个代码有一些对实用方法的引用,但是它们的实现在上下文中应该是显而易见的):

 /** * Add classPath to this loader's classpath. * <p> * The classpath may contain elements that include a generic file base name. A generic basename * is a filename without the extension that may begin and/or end with an asterisk. Use of the * asterisk denotes a partial match. Any files with an extension of ".jar" whose base name match * the specified basename will be added to this class loaders classpath. The case of the filename is ignored. * For example "/somedir/*abc" means all files in somedir that end with "abc.jar", "/somedir/abc*" * means all files that start with "abc" and end with ".jar", and "/somedir/*abc*" means all files * that contain "abc" and end with ".jar". * */ public void addClassPath(String cp) { String seps=File.pathSeparator; // separators if(!File.pathSeparator.equals(";")) { seps+=";"; } // want to accept both system separator and ';' for(StringTokenizer st=new StringTokenizer(cp,seps,false); st.hasMoreTokens(); ) { String pe=st.nextToken(); File fe; String bn=null; if(pe.length()==0) { continue; } fe=new File(pe); if(fe.getName().indexOf('*')!=-1) { bn=fe.getName(); fe=fe.getParentFile(); } if(!fe.isAbsolute() && pe.charAt(0)!='/' && pe.charAt(0)!='\\') { fe=new File(rootPath,fe.getPath()); } try { fe=fe.getCanonicalFile(); } catch(IOException thr) { log.diagln("Skipping non-existent classpath element '"+fe+"' ("+thr+")."); continue; } if(!GenUtil.isBlank(bn)) { fe=new File(fe,bn); } if(classPathElements.contains(fe.getPath())) { log.diagln("Skipping duplicate classpath element '"+fe+"'."); continue; } else { classPathElements.add(fe.getPath()); } if(!GenUtil.isBlank(bn)) { addJars(fe.getParentFile(),bn); } else if(!fe.exists()) { // s/never be due getCanonicalFile() above log.diagln("Could not find classpath element '"+fe+"'"); } else if(fe.isDirectory()) { addURL(createUrl(fe)); } else if(fe.getName().toLowerCase().endsWith(".zip") || fe.getName().toLowerCase().endsWith(".jar")) { addURL(createUrl(fe)); } else { log.diagln("ClassPath element '"+fe+"' is not an existing directory and is not a file ending with '.zip' or '.jar'"); } } log.diagln("Class loader is using classpath: \""+classPath+"\"."); } /** * Adds a set of JAR files using a generic base name to this loader's classpath. See @link:addClassPath(String) for * details of the generic base name. */ public void addJars(File dir, String nam) { String[] jars; // matching jar files if(nam.endsWith(".jar")) { nam=nam.substring(0,(nam.length()-4)); } if(!dir.exists()) { log.diagln("Could not find directory for Class Path element '"+dir+File.separator+nam+".jar'"); return; } if(!dir.canRead()) { log.error("Could not read directory for Class Path element '"+dir+File.separator+nam+".jar'"); return; } FileSelector fs=new FileSelector(true).add("BaseName","EG",nam,true).add("Name","EW",".jar",true); if((jars=dir.list(fs))==null) { log.error("Error accessing directory for Class Path element '"+dir+File.separator+nam+".jar'"); } else if(jars.length==0) { log.diagln("No JAR files match specification '"+new File(dir,nam)+".jar'"); } else { log.diagln("Adding files matching specification '"+dir+File.separator+nam+".jar'"); Arrays.sort(jars,String.CASE_INSENSITIVE_ORDER); for(int xa=0; xa<jars.length; xa++) { addURL(createUrl(new File(dir,jars[xa]))); } } } private URL createUrl(File fe) { try { URL url=fe.toURI().toURL(); log.diagln("Added URL: '"+url.toString()+"'"); if(classPath.length()>0) { classPath+=File.pathSeparator; } this.classPath+=fe.getPath(); return url; } catch(MalformedURLException thr) { log.diagln("Classpath element '"+fe+"' could not be used to create a valid file system URL"); return null; } } 

您可以实现自己的类加载器 ,但该类/ jar必须位于类path中才能执行。

尝试

 java -cp *.jar:. myClass 

要么

 export CLASSPATH=./lib/tool.jar:. java myClass 

要么

 java -jar file.jar 

我不得不同意其他两个海报,这听起来像是在过分复杂的testing课。 将.java和.class文件放在单独的文件夹中并不是那么不寻常,而依赖于jar文件还有三分之一,不需要编程改变类path。 如果你这样做,因为你不想每次都在命令行input类path,我会build议一个shell脚本或batch file。 更好的是,一个IDE。 我真的有这个问题,你为什么要尝试在代码中pipe理类path?

您可以编写batch file或shell脚本文件来导出类path并运行java程序。 在Windows中,

set classpath =%classpath%; ../ classes; ../ jars / * java ParserTester

在Unix中,导出classpath =%classpath%:../ classes:../ jars / * java ParserTester

如果将文件名称命名为parser.bat或parser.sh,则可以通过在相应的OS中调用parsing器来运行该文件。

从java 1.6开始,你可以把所有的jar包放到classpath中,只需要说/ *

如果要dynamic生成一个java文件,编译并添加到类path中,请事先在类path中设置生成类文件的目录。 它应该加载类。 如果你正在修改已经生成的java类,基本上修改后重新编译,如果你想加载新的类,你需要使用你的自定义类加载器来避免类的caching。

我理解对吗? 你有没有想要启动你的类而不指定类path并在运行时加载它的唯一原因? …

java parserTester

代替

java -classpath ../classes;../jar ;. parserTester

可能我没有得到你的理由。 但是,如果“那是”你想要的东西,你可以做以下事情(尽pipe对我来说没有什么意义)

  • 启动课程
  • 从主要方法lauch另一个类编程方式设置类path在那里。
  • 历史的结束。

像下面的“java -pseudo代码”

 public static void main( String [] args ) { String classpath = "classes;../jar"; Runtime.getRuntime().execute("java + classpath + " parserTester "); } 

请告诉我,如果我得到它的权利。 如果你想做别的事情,我会很乐意帮忙的。

我想你想要的是一个“执行包装器”或平台特定的“启动器”…通常这个组件是用来检测您的操作系统,体系结构和依赖关系,然后进行调整之前启动您的应用程序。 这是一个老派的devise模式(说80年代和更早),但今天仍然使用很多。 这个想法是,你的程序可以是系统和环境不可知的,发射器将做好准备并告诉软件它需要知道的一切。 许多现代的开源程序都使用Shell脚本和batch file等来完成这个任务。例如Apache Tomcat。 你可以很容易地使用java中的包装,使用命令行exec来启动软件(一定要在* NIX的exec命令末尾加上“&”,这样你的包装就可以退出,只剩下你的软件正在运行。 ..也可以让你closuresshell窗口而不杀死进程)

非常好的post,在我的情况下,我做到了这一点工作良好(注:Windows具体):

 set classpath=%classpath%;../lib/* java -cp %classpath% com.test.MyClass