The labs on this site need JavaScript to run. The same content is written out below.
Fundamentals › Java
What is a library, and what happens when it is missing?
A library is a set of classes that someone else has made. In this lab, one class, lib.Greeter, is packed into a jar file (a file that bundles class files) named greet.jar. My code, App.java, uses that class with import lib.Greeter;, but Greeter is not inside App.java. So both when compiling and when running, the compiler (javac) and the JVM (java) have to find Greeter on the class path (a list of places to look for class files), and in the command you write that list after -cp. The libraries that my project uses are called dependencies, and in the build tool Gradle, a dependency declared with implementation goes into the class path for both compiling and running. In this lab you take greet.jar out of the javac command and the java command one at a time, and the real compile and run happen, to show which error occurs at which step. (Gradle is not run in this lab.)
Checked against real execution · Built greet.jar on JDK 21 and ran the javac and java commands exactly as shown in 4 combinations, then checked the results against them
# App.java
// Import a class made by someone else, which is inside greet.jar
import lib.Greeter;
public class App {
public static void main(String[] args) {
System.out.println(Greeter.hello("kim"));
}
}
# greet.jar (Greeter.java compiled and packed into a jar)
package lib;
public class Greeter {
public static String hello(String name) {
return "hello, " + name;
}
}
# Terminal
javac -cp greet.jar App.java
java -cp greet.jar;. App
The compiler and runtime are JDK 21.0.12.1 (javac 21, java 21). All 4 combinations were checked. First, the class lib.Greeter (with one method, hello) was packed into greet.jar with javac and the jar tool (no external jar was downloaded), and for each combination, greet.jar and App.java were placed in a new folder and the terminal commands javac and java written on the screen were run exactly as written. The code on the screen is the same text that the probe made and kept from the actual file contents and the commands actually run. What was checked is whether the compile succeeded, the number of errors and the diagnostic codes (compiler.err.doesnt.exist and compiler.err.cant.resolve.location were rendered as the two error descriptions on the screen) and the lines where the errors occurred, whether App.class was created, the exit code and output of the java command, and the kind of the run error (NoClassDefFoundError) and its location (App.java:6). In the combinations where the compile failed, the java command was also actually run, and I confirmed that the error that the class App cannot be found occurs. The facts that the step sentences rely on were also checked by separate runs. These are that greet.jar contains lib/Greeter.class (jar tf), that the only class file created in the folder where the compile succeeded is App.class, that if you write only -cp greet.jar in the java command and leave out the dot (.), it cannot find App.class in the current folder, and that before the compile the folder had only App.java and greet.jar. The commands were run on Windows 11, and the semicolon (;) as the class path separator is for Windows (a colon on macOS and Linux). The screen shows only that one form. The CLASSPATH environment variable was cleared in the process that ran them, and in an environment where this variable is set, the result of a command without -cp can differ. The error sentence of the java launcher is shown in English; it was obtained by running the java command again with -Duser.language=en. On the PC used to write this lab (Korean Windows), without that option the sentence came out in Korean, and with other language settings the sentence is different. I opened the documentation and checked it. These are, in the javac tool documentation from Oracle (https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html), that --class-path (-cp) sets where to look for user class files, that the current folder is used if neither -cp nor the CLASSPATH environment variable is set, and that the separator is a semicolon on Windows; in the java tool documentation (https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html; I read only the first 100,000 characters, and the explanation of -cp was within them), that -cp is a list of directories, JAR files, and ZIP files in which to look for class files, and that if it is not specified, it is the current folder (.); in the NoClassDefFoundError API documentation (https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/NoClassDefFoundError.html), that it is thrown when a class definition is to be loaded and cannot be found, and that it is the case where a definition that existed at compile time can no longer be found; in the Gradle documentation Declaring dependencies (https://docs.gradle.org/current/userguide/declaring_dependencies_basics.html), that a module dependency is written as group:name:version coordinates, with an example of writing it with implementation inside dependencies; and in the Java Plugin documentation (https://docs.gradle.org/current/userguide/java_plugin.html), in the table of configurations, that implementation is a dependency needed both at compile time and at run time and is included in compileClasspath and runtimeClasspath. Gradle was not run, and the process of downloading jars from a repository could not be checked in the documentation either, so it is not described. The number and kinds of errors and the error sentences are not set by a specification but were observed on this JDK. Beyond that, a library pulling in other libraries (transitive dependencies), versions, the order when the same class is in several places on the class path, and the module system are not covered. Dependencies and the supply chain are covered in the in-depth lab "Dependencies and the supply chain", and Spring Boot, which looks at the dependencies and creates the configuration automatically, is covered in the in-depth lab "Spring Boot auto-configuration".
Struck-through text was removed from the first version of the code; highlighted text was added.