https://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html specifies:
The default class path is the current directory. Setting the CLASSPATH variable or using the -classpath command-line option overrides that default, so if you want to include the current directory in the search path, you must include "." in the new settings.
So, to add to that default, include the CLASSPATH environment variable in your invocation:
java -cp ".;C:\Path\to\my\magical\jarfile.jar;.\some\other\directory;%CLASSPATH%"
Answer from Justin Pierce on Stack OverflowVideos
I'm not a Java programmer, so I don't know the correct value for CLASSPATH. But, you seem to. You can add it to ~/.bashrc like so:
CLASSPATH=/path/to/1:/path/to/2:/etc
The change will take effect globally the next time you log in. However, it will take effect immediately in new shells.
Additionally, if you want to set it for just one particular command, do this:
CLASSPATH=/something command-here arg1 arg2
A third way would be to create a wrapper script, which would be appropriate if you needed to set multiple variables or if you needed to determine appropriate values programmatically:
#!/bin/bash
export CLASSPATH=/something
export ANOTHER_ENV_Variable=foo
exec your_fancy_program "$@"
that's what happened with me.. i left empty spaces while typing.. it fixed when i removed spaces.
1) if you want to set classpath permanently then 1) find out where java is installed.. you may use " whereis java " openjdk-7/6 is in /usr/lib/jvm/.....
2) we need to set up CLASSPATH in /etc/environment
sudo gedit /etc/environment
3) add the following likes .. ( DONT LEAVE ANY SPACES WHILE TYPING)(customize according to your java version and installation) (this home path is for open jdk 7)
JAVA_HOME="/usr/lib/jvm/java-7-openjdk-i386/bin"
export JAVA_HOME
CLASSPATH=".:/usr/lib/jvm/java-7-openjdk-i386/lib:/home/laptop/Desktop/a2"
export CLASSPATH
separate directory by ":"
You can only add folders or jar files to a class loader. So if you have a single class file, you need to put it into the appropriate folder structure first.
Here is a rather ugly hack that adds to the SystemClassLoader at runtime:
import java.io.IOException;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;
public class ClassPathHacker {
private static final Class[] parameters = new Class[]{URL.class};
public static void addFile(String s) throws IOException {
File f = new File(s);
addFile(f);
}//end method
public static void addFile(File f) throws IOException {
addURL(f.toURL());
}//end method
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[]{u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}//end try catch
}//end method
}//end class
The reflection is necessary to access the protected method addURL. This could fail if there is a SecurityManager.
Try this one on for size.
private static void addSoftwareLibrary(File file) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}
This edits the system class loader to include the given library jar. It is pretty ugly, but it works.
You can use a java.net.URLClassLoader to load classes with any program defined list of URL's you wish:
public class URLClassLoader extends SecureClassLoader
This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories. Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed.
The AccessControlContext of the thread that created the instance of URLClassLoader will be used when subsequently loading classes and resources.
The classes that are loaded are by default granted permission only to access the URLs specified when the URLClassLoader was created.
Since: 1.2
And a little fancy footwork can extend it to support using wildcarded pathnames to pick up entire directories of JARs (this code has some references to utility methods, but their implementation should be obvious in the context):
/**
* 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;
}
}
I have to agree with the other two posters, it sounds like you're overcomplicating a test class. It's not that unusual to have the .java and .class files in separate folders, while depending on jar files in yet a third, without programmatically changing the classpath. If you're doing it because you don't want to have to type the classpath on the command line everytime, I would suggest a shell script or batch file. Better yet, an IDE. The question I really have is why are you doing trying to manage the classpath in code?
Using Java 6 or later, the classpath option supports wildcards. Note the following:
- Use straight quotes (
") - Use
*, not*.jar
Windows
java -cp "Test.jar;lib/*" my.package.MainClass
Unix
java -cp "Test.jar:lib/*" my.package.MainClass
This is similar to Windows, but uses : instead of ;. If you cannot use wildcards, bash allows the following syntax (where lib is the directory containing all the Java archive files):
java -cp "$(printf %s: lib/*.jar)"
(Note that using a classpath is incompatible with the -jar option. See also: Execute jar file with multiple classpath libraries from command prompt)
Understanding Wildcards
From the Classpath document:
Class path entries can contain the basename wildcard character
*, which is considered equivalent to specifying a list of all the files in the directory with the extension.jaror.JAR. For example, the class path entryfoo/*specifies all JAR files in the directory named foo. A classpath entry consisting simply of*expands to a list of all the jar files in the current directory.A class path entry that contains
*will not match class files. To match both classes and JAR files in a single directory foo, use eitherfoo;foo/*orfoo/*;foo. The order chosen determines whether the classes and resources infooare loaded before JAR files infoo, or vice versa.Subdirectories are not searched recursively. For example,
foo/*looks for JAR files only infoo, not infoo/bar,foo/baz, etc.The order in which the JAR files in a directory are enumerated in the expanded class path is not specified and may vary from platform to platform and even from moment to moment on the same machine. A well-constructed application should not depend upon any particular order. If a specific order is required then the JAR files can be enumerated explicitly in the class path.
Expansion of wildcards is done early, prior to the invocation of a program's main method, rather than late, during the class-loading process itself. Each element of the input class path containing a wildcard is replaced by the (possibly empty) sequence of elements generated by enumerating the JAR files in the named directory. For example, if the directory
foocontainsa.jar,b.jar, andc.jar, then the class pathfoo/*is expanded intofoo/a.jar;foo/b.jar;foo/c.jar, and that string would be the value of the system propertyjava.class.path.The
CLASSPATHenvironment variable is not treated any differently from the-classpath(or-cp) command-line option. That is, wildcards are honored in all these cases. However, class path wildcards are not honored in theClass-Path jar-manifestheader.
Note: due to a known bug in java 8, the windows examples must use a backslash preceding entries with a trailing asterisk: https://bugs.openjdk.java.net/browse/JDK-8131329
Under Windows this works:
java -cp "Test.jar;lib/*" my.package.MainClass
and this does not work:
java -cp "Test.jar;lib/*.jar" my.package.MainClass
Notice the *.jar, so the * wildcard should be used alone.
On Linux, the following works:
java -cp "Test.jar:lib/*" my.package.MainClass
The separators are colons instead of semicolons.