This articles covers some questions and answers you may want to know about java classpath. These questions are not very common in interviews, however I find them interesting. Some people use them for screening developers fundamental understanding of java.
Beginners learning java may find this article a little more useful, however I have tried to cover questions of various complexity including simple to very difficult ones like custom class loading and hacks related to java classpath.
The classpath is the location where the Java Virtual Machine search for user-defined classes, packages and resources in any Java program. Below is a list of some java interview questions on CLASSPATH that may give you an edge over others in your next Java interview.
Java Interview Preparation Tips
- Part 0: Things You Must Know For a Java Interview
- Part 1: Core Java Interview Questions
- Part 2: JDBC Interview Questions
- Part 3: Collections Framework Interview Questions
- Part 4: Threading Interview Questions
- Part 5: Serialization Interview Questions
- Part 6: Classpath Interview Questions
- Part 7: Java Architect Scalability Questions
Why Java uses Classpath parameter or environment variables?
In a Java class import statements are used to access other classes. You also do a wild card import like org.fromdev.* on your java file.
In such cases, It will become very impractical/slow for the Java Virtual Machine to search for classes in every file/folder on a machine, therefore you can provide the Java Virtual Machine with a list of places to look. This is done by putting folder and jar files on your classpath.
Environment variables in general are a set of dynamic name value pair that can be used by processes to decide the behavior based on a system. These are supported by all modern operating systems.
The CLASSPATH variable is a Java way to tell the possible locations of user classes or jar files for a Java application. Since each user/computer may choose to have classes in different location its best to have custom locations configured in Classpath variable.
In case you have not set the classpath environment variable, the default value is used as the “.” (current directory). That means, the current directory is searched.
When does Java read values of Classpath environment variable?
Java uses the CLASSPATH environment variable to read the classes and libraries from file system. This variable is used by all JDK Tools and Extension including Java Compiler (javac) and JRE(java) use this variable to locate the dependent user classes and jar files to perform specific tasks.
Java Compiler uses it to locate the dependent user classes and jar files to compile Java source files.
Java Run-time Environment (JRE) uses the classpath variable to identify the location of files to be loaded for the run-time dependencies (e.g. classes and jar files) of java program.
How to set Java Classpath on Windows, Unix, Linux and Mac?
Setting CLASSPATH on Windows XP
Follow below steps on Windows XP to set Java CLASSPATH
- Right-click My Computer, and then click Properties.
- Click the Advanced tab.
- Click Environment variables.
- Click one the following options, for either a user or a system variable
- Click New to add a new variable name and value.
- Enter Variable name as CLASSPATH
- enter all directories and jar files separated by semicolon. (e.g. c:dir1;c:dir2;c:dir3abc.jar)
Setting CLASSPATH on Windows 7
- Click Start
- Then right-click on Computer,
- select Properties
- click Select Advanced System Settings tab.
- click the Environment Variables button.
Setting CLASSPATH on Unix, Linux and Mac
Use export command to set the CLASSPATH environment variable in your system.
export CLASSPATH=/path/to/dir1:/path/to/dir2:path/to/abc.jar
How do I check the CLASSPATH variable is set in my machine?
Checking CLASSPATH on Windows
To check CLASSPATH variable is set on Microsoft Windows, run following command on command prompt
C:> echo %CLASSPATH%
If CLASSPATH variable is not set you will see %CLASSPATH% on windows system.
Checking CLASSPATH on Unix, Linux or Mac
To check CLASSPATH variable is set on Unix/Linux/Mac run following command on shell
$ echo $CLASSPATH
If CLASSPATH variable is not set you will see CLASSPATH: Undefined variable error on Unix/Linux/Mac systems.
How to set Multiple Jar Files in Java Classpath
Java versions Older then Java 6 does not support wildcard characters. Setting Multiple jars using wildcard in Java classpath are allowed in Java 6 and later versions.
For example, to specify all jar files in a directory “lib” the classpath entry should look like this
lib/*
The wildcard entry (*) in classpath value will match only jar files NOT class files. To match both class files and JAR files in a same directory lib, you need to specify both values as shown below
Setting Multiple Jars in Classpath on Windows
Windows environment variable values are separated by semicolon, therefore you classpath entry would look like this
lib/*;lib
Setting Multiple Jars in Classpath on Unix, Linux or Mac
Unix environment variable values are separated by colon, therefore you classpath entry would look like this
lib/*:lib
Older version of Java
In older version of Java(older than Java 6), each jar file needs to be specified in the classpath. It can be a tedious and erroneous task if you are using many third party libraries.
What is the difference between NoClassDefFoundError and ClassNotFoundException? When NoClassDefFoundError and ClassNotFoundException are thrown?
NoClassDefFoundError and ClassNotFoundException are very closely related and often confused with each other by many developers. Below is the description of each from the Java API Specifications
ClassNotFoundException
Thrown when an application tries to load in a class through its string name using:
- The forName method in class Class.
- The findSystemClass method in class ClassLoader.
- The loadClass method in class ClassLoader.
but the definition of the class with the specified name could not be found due to following reasons
- The specified name class does not exist.
- The specified name class is not in the classpath
- The specified name class is not visible to the classloader.
NoClassDefFoundError
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
Key Differences
- The NoClassDefFoundError is thrown when the source was successfully compiled, but during runtime, the required class files were not found. This may be a case when some dependency jar files were not included or not in classpath.A ClassNotFoundException is thrown when the reported class is not found by the ClassLoader or not visible to the Classloader.
- Another important distinction between these two is, NoClassDefFoundError is a sub class of java.lang.Error and the ClassNotFoundException is a subclass of java.lang.Exception.
- NoClassDefFoundError is a critical error for JVM since its having problems finding a class it expected to find.On the other hand, the ClassNotFoundException is an Exception. Use of reflection api can be error-prone and there is no compile-time check to validate reflection call is loading right classes, so there can be situations when some classes may not be found.
Some scenario when ClassNotFoundException may occur
Scenario 1 (Use of reflection) – You will see ClassNotFoundException when you are using reflection to load classes at runtime, and the class you are trying to load does not exist or not in classpath.
Scenario 2 (Multiple Classloaders being used) – You will see ClassNotFoundException when a class is being loaded from another class which was already loaded in a parent classloader and the class from the child classloader is not visible.
How can we include Jar within a Jar in java classpath?
There is no easy way to do this in current java versions. There are 2 alternatives to deal with this problem using third party libraries
Use Jar class loader library
The JarClassLoader library provides you the feature of loading resources from a top JAR and from JARs inside the top JAR.
Explode and combine into one jar
Instead of trying to bundle jar file inside jar you can explode all required jars and re-bundle them as one jar using following two libraries
- The first is One-Jar, which uses a special classloader to allow the nesting of jars.
- The second is UberJar, (or Maven Shade Plugin), which explodes the included libraries and puts all the classes in the top-level jar.
How to read a file from CLASSPATH in java?
This can be done in two simple ways
Using ClassLoader.getResourceAsStream
This method can be used to load any file from CLASSPATH
InputStream in =this.getClass().getClassLoader().getResourceAsStream("MyFile.txt");
Using Class.getResourceAsStream
This method can be used to load files using relative path to the package of the class
InputStream in =this.getClass().getResourceAsStream("SomeTextFile.txt");
This method can also be used to load any files from CLASSPATH by prefixing a “/”
How to find which jar file is being used by Java run-time?
On Windows
You need use below windows program Process Explorer that lets you see which files are open for a particular process or program
On Unix, Linux or Mac
It can be done using lsof command. lsof is one of my favorite and useful java debugging commands on Unix. Below is the syntax for using this command –
lsof -p [pid]
How to find the load location of a Java class file at run-time?
There are two ways to find it
Using Classloader
Below code snippet can be used to find the location of java class com.fromdev.MyClass
this.getClass().getClassLoader().getResource(“com/fromdev/MyClass.class”)
Using Protection Domain
We can use this to find the exact location a jar file containing the class JVM is using
clazz.getProtectionDomain().getCodeSource().getLocation()
How Java handles Two classes with same name in classpath
If I have two classes with same name say MyClass.java in two different jar in my classpath which one will be picked up by JVM , is there anyway I can suggest JVM to pick a specific one ?
Java interpreter loads classes based on the order they are specified in the CLASSPATH variable.
For example, lets say this is your classpath variable value
C:ProjectDir1;C:ProjectDir2
The Java interpreter will first look for MyClass class in the directory C:ProjectDir1. Only if it doesn’t find it in that directory it will look in the C:ProjectDir2 directory.
How to Add A Jar File To Java Load Path At Run Time
This can done by use of URLClassloader. A sample implementation of this code is shown below
import java.net.URL; import java.net.URLClassLoader; public class SimpleJarLoader { public static void main(String args[]) { if (args.length < 2) { System.out.println("Usage: [Class name] [Jar Path]"); return; } try { System.out.println("Trying to load the class..."); Class.forName(args[0]); } catch (Exception ex) { System.out.println("Not able to load class..." + args[0]); } try { String url = "jar:file:/" + args[1] + "!/"; URL urls[] = { new URL(url) }; URLClassLoader cl = new URLClassLoader(urls, SimpleJarLoader.class.getClassLoader()); System.out.println("Looking into jar... " + url); cl.loadClass(args[0]); System.out.println("Woohoo....I found it"); } catch (Exception ex) { System.out.println("Oops...Still cant find the jar"); ex.printStackTrace(); } } }
You can run this code by below command. (Make sure to use forward slash “/” as directory separator.)
java SimpleJarLoader org.springframework.core.SpringVersion C:/spring.jar
The output is like this
Trying to load the class... Not able to load class...org.springframework.core.SpringVersion Looking into jar... jar:file:/C:/spring.jar!/ Woohoo....I found it
Why calling System.setProperty() does not affect the classpath at run-time?
You can easily set any system properties in java using System.setPropoerty method, However it may not have any effect in case of CLASSPATH property. This is mainly because the Java system class loader is initialized very early in the JVM startup sequence. The class loader copies the classpath into its own data structures, and the classpath property is not read again. Therefore changing it after its already copied does not affect anything. There are mainly two reasons for this – First most important reason is security. You do not want a malicious code change the classpath at runtime and load some unwanted classes. Second reason is performance, since reading the classpath every-time its needed may not be efficient.
How to Add A Jar File To Java System Classpath At Run-time?
This can be done by using a simple reflection API hack as demonstrated in below sample code. This example assumes you have a file “c:/Sample.txt” that is not already in class path and at run-time c:/ is added the System classpath and then Sample.txt is made available.
import java.io.File; import java.io.InputStream; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; public class HackJavaClasspath { public static void addURL(URL url) throws Exception { URLClassLoader cl = (URLClassLoader) ClassLoader .getSystemClassLoader(); Class clazz = URLClassLoader.class; Method method = clazz.getDeclaredMethod("addURL", new Class[] { URL.class }); method.setAccessible(true); method.invoke(cl, new Object[] { url }); } public static void main(String[] args) throws Exception { //Add c: to the classpath addURL(new File("c:/").toURI().toURL()); //Now load the file from new location InputStream in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("Sample.txt"); System.out.println(in.available()); } }
Running this java class prints the number of bytes available. This indicates the file is available for further processing.
How to get a list of resources from a directory in Java classpath?
You can use Reflections library for doing this. Reflections is a open source Java library. It scans Java classpath and indexes it with metadata. This library allows you to query the classpath at runtime and can be very handy for many run-time reflection code needs.
Can you think of more topics that are not part of this post? Feel free to share it with us in comments & we will try to improve this article. Hopefully making it best resource for future reference.