Understanding the Importance of CLASSPATH in Java

Classpath is a way of telling your Java class and JDK tools where to find another user-defined class, written by you or others. If you program in Java, without any package declaration, you may compile and run the program without worrying about what a classpath is, as there is  a default classpath setting in JDK. But you cannot create any significant Java Project with that approach. Packages in Java are similar to Modules or Namespace in other languages. It allows you to organize your code-base,  that may otherwise become un-manageable. Most of our earlier Java programs used package declarations. Learning what a Class path is necessary in such cases for making package declarations correctly.  But there was no discussion on Class path in those articles, as we made use of Integrated Development Environments/Tools -either Eclipse or NetBeans – IDE. IDEs have their own ways of manipulating the class path and the package declarations are also generated when we ask the IDE to create a new Java Class. Earlier  in DIQ , we had a few articles where we used Command prompt to compile and run our samples and we had some discussion on CLASSPATH. Now we will have a relook at the same, as Java still has a very large user-base and it will be useful to them.

IDEs increase the productivity but enables you to avoid learning some technicalities:

The IDEs- enhance the productivity of a Java programmer. If the programmer uses an editor and invokes the JDK tools javac and java through command line, he may have to set the Path and ClassPath environment variables himself and write all the code manually. But the gain in productivity is at a cost. The widespread use of IDEs conceals the technicalities and there is a lack of comprehension about the importance and even the difference between environment variables like path, classpath etc. The variable PATH is simple.   In the Control Panel, you have to set the PATH Environment Variable pointing to the location of any exe file or application; for example, scala/bin, .lein/bin  erl/bin, elixir/bin or  jdk/bin in the File System. Then in the command prompt from anywhere, you can invoke the lein tool for clojure , erl for Erlang or mix or iex tools for Elixir or  “javac” or “java” JDK  tools, without furnishing the full-path to the same. CLASSPATH is more complicated. The Java compiler and the JVM use the CLASSPATH to search and locate user-defined classes when they are referenced in another Java class. Our samples will throw more light.

Sample
A Java Programmer, after installing JDK , would have set JAVA_HOME environment variable setting, as many Java tools, or even Scala  requires that. In Windows-7,   the step is : Control Panelà System and SecurityàSystem àadvanced system setting à Environment variables under System Variables you can click New and fill up the wizard that appears with necessary details ie your JDK installation folder. In my case F:\Java\jdk1.7.0_79.Then edit the path variable to append %JAVA_HOME%\bin. We can check in the command prompt by executing

java –version.

If we see “java version ……” the environment is ready for use. We need a folder/directory to put our Java code. We will use F:\javaPro as a parent\base directory - to hold our sub-directories that mirror the package declaration in Java source files .See the declaration in a  source-code below:

Sample
package sample.example;  nested sub-folders required under parent directory F:\javaPro

 

This means that we require -within the parent directory- a nested directory structure as shown above to mirror the package declaration. The source code should be placed in example sub-directory.
Source files

F:\javaPro\sample\example\Employee.java

package sample.example; ------1]
public class Employee {
int sal=6000;

    public void show(){
System.out.println("Employee's salary =" + sal);
}

}

1) Package declaration carves out a namespace for our app from Global namespace and segregates it. In naming our class we need not worry now whether there is class of the same name-Employee- in the Global namespace. If we don’t declare a package in the source file,  it will be stored in default package and we have to be extra-careful to avoid class-name collisions.

In the command prompt if we change to example directory which contains our java source files  and execute
javac Employee.java
the file will be compiled.
By  executing
javap –c  Employee

You can disassemble class file and get a mnemonic version of the generated byte-code. You can have a look at the byte-code and see the core classes java.lang and java.io are used, even though you did not import them explicitly. These core java classes and the system “jar “files jvm/lib and jvm/lib/ext are searched and used automatically. The problem arises only when our java code references another user-defined java class, as we will see below. Look at the code of the following source file Main.java

F:\javaPro\sample\example\Main.java

package sample.example;
public class Main {

  public static void main(String[] args)
{
Employee e = new Employee();  // reference to Employee class
e.show();
}
}

Try to compile the above file “Main.java”from example directory .You will get an error message which says “can not find symbol class Employee”. Why this error occurs, despite having both the java files located in the same sub-directory “example” and earlier compiling Employee.java. You can even see the Employee class file in the “example” sub-folder and even had a look at the byte-code using javap tool.  Then why the compiler, while trying to compile Main.java fails to see it. As Main.java references Employee class, the compiler will look for the CLASSPATH setting to start the search for the package which contains the class from the directory specified there. As no –classpath option is explicitly passed, by default the search will start from current directory, which here is[parent]/ sample/example. The tools will look at the package tree to locate the Employee.class . The compiler will look for a directory sample/example below the current directory. As we have made /sample/ example the current directory, the compiler will look for a Java class file in the directory [parent]/sample/example/sample/example which, of course, does not exist. See the figures below:

Directory structure 

As shown in the figures, the tools start the search in current directory and proceeds to all sub-directories in the package declaration. So the base-folder.ie the directory before the package tree should be made the current directory – the directory in the command prompt to compile the java files. If we compile the files from the base-folder ,ie the folder above package tree there will be no Class-Not-Found error. ie ,we can compile the files sample\example\Employee.java and sample\example\Main.java separately without the compiler raising any error, due to default classpath. But the separate compilation of source files is not required as we see below:   
           
In the command prompt change to F:\javaPro and execute

javac sample\example\Main.java
It will compile not only “Main.java” but also the file Employee.java, as Main.java references the class Employee.
You can execute
java sample.example.Main
and see the result “Employee’s salary to 6000”

In other words, when we use default CLASSPATH,  the compiler and run time will start looking for referenced class files from the current directory and go to its sub-directories. The core java classes java.lang and java.io and runtime library files (rt.jar and the other JAR files in the jre/lib and jre/lib/ext directories) are always searched for classes.

Instead of relying on default class-path, you can explicitly pass classpath option while executing javac and java commands as under:

F:\javaPro >javac –classpath “.”    sample\example\Main.java
F:\javaPro >java -classpath “.” sample.example.Main

“.” Refers to the current directory.

Instead of passing –class-path option while executing commands in Command prompt, you can set the class-path in a batch file and execute it and this comes in handy when you have to use third-party jar files in your application and add them to the class-path. The classes in jar files in the class-path will also be searched

Another Sample

Look at the example below which uses JDBC API. The Java JDBC API enables Java applications to connect to relational databases via a standard API, and our app retrieves data from MySQL database using the API. Create two sub-directories “db” and “lib” under base directory F:\javaPro.

You can put the driver mysql-connector-java-5.1.18-bin.jar in “lib” sub-directory and the source files in “db” sub-directory. You have to put the batch file in the base folder F:\javaPro. The bat file will look as under:

\cl.bat

set CLASSPATH=F:\javaPro;.;F:\javaPro\lib\*;


The CLASSPATH environment variable is set with a semicolon-separated list of directories and class archive files.

We have specified the base-folder F:\javaPro; but once again we use “.” to refer to the current directory. Why? The javac compiler always looks for files in the current directory, but the java virtual machine launcher only looks into the current directory if the “.” directory is on the class path. If you have no class path set, this is not a problem—the default class path consists of the “.” directory. But if you have set the class path and forgot to include the “.” directory, your programs will compile without error, but they won’t run. We have used “*” to refer to all jar files under “lib” sub-directory

Database schema
In MySQL create a database “Sample” and a table book with the following schema.
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
author VARCHAR(50);
Add a few records.

Source file
The source files has to be kept under “db” sub-folder under base-folder F:\javaPro.
The source file will look as under:

F:\javaPro\db\SqlBean.java

package db;
import java .sql.*;
import java.util.*;

public class SqlBean
{

public static void main(String args[] )
{
String url="jdbc:mysql://localhost/sample";
Connection conn = null;
Statement stmt = null;
try
{
Class.forName("com.mysql.jdbc.Driver"); //load driver

 /**get a connection  from DriverManager passing url, username and password   */
conn =DriverManager.getConnection(url,"madhan","madhan");

  stmt=conn.createStatement(); //---1)
String sql;
sql = "SELECT * from book";
ResultSet rs=stmt.executeQuery(sql);  //----2)

      while(rs.next())   //------3)

      {
String title = rs.getString("title");  //------4)
String author  = rs.getString("author");

    System.out.println(title);
System.out.println(author);
}

rs.close();
stmt.close();
conn.close(); 

      }catch(Exception e1)
{System.out.println(" " +e1);
}
}
}

  1. Get a statement object from connection object. A Statement is used to execute queries and updates against the database
  2. When you perform a query against the database you get back a ResultSet.
  3. You can then traverse this ResultSet to read the result of the query
  4. From the ResultSet containing the DB data, the values for particular columns are extracted.

Compile and Run

In the command prompt change to base-folder F:\javaPro.Execute the following commands:

cl.bat   //sets the class-path
javac db\SqlBean.java
java db.SqlBean

You can see the records you added in the database displayed in the command prompt.

Conclusion

IDEs increase the productivity of a java programmer – for that matter any programmer; but they shroud some basic technicalities. We can set “path” environment variable permanently through control panel and simplify invocation of jdk tools like javac and java in the command prompt. But we don’t have to set permanently “CLASSPATH” variable in the control panel. If we don’t use third party jars, we may not need to explicitly set CLASSPATH when we execute the commands from parent directory – ie the folder containing the package tree. Then the default CLASSPATH is used and it starts the search for classes from the current directory and also searches its sub-directories which are part of the package tree. The core java files in java.lang and java.io. and jars in the JRE/lib and JRE/lib/ext will also be automatically searched. In other words if we execute javac and java commands from the parent directory (which holds the user-defined package and the java files) the compiler and JVM will make searches for classes in that directory and its sub-directories. If we use third-party jar files we have to explicitly set CLASSPATH, preferably in a bat file as given earlier in the sample. The bat file has to be executed before executing javac and java commands The CLASSPATH thus set is temporary and meant only for this application and lives till the command prompt is closed. Java is a widely used language and the number of existing projects and user base is very large, though its rate of adoption for new projects is not big. Still it is the number one server-side programming language. Understanding how the CLASSPATH works is an essential skill in Java and this article is an attempt to provide it, as the materials on the subject available on web is rather confusing. The article “Mastering the Java CLASSPATH”  by Kevin Boone is explains the concepts well and is very useful. In our article, to keep things simple, explanations regarding the syntax of the language have been  kept minimal.








}