Home > Net >  Why projects work properly without setting classpath environment variable?
Why projects work properly without setting classpath environment variable?

Time:01-30

I try to understand what CLASSPATH does for Java and Spring Boot projects. And I see that it is am environment variable and it is used to provide the root of any package hierarchy to java compiler. But I didn't set this CLASSPATH, it's missing from environment variables and the projects are working properly. I set only the PATH environment variable and I put the location of jdk/bin.

On the other hand, I'm working now at a multimodule Maven project on Intellij, and for example if I try to use the class ObjectMapper in a module where I don't have the dependency it says:

Cannot resolve symbol 'ObjectMapper'

Add library 'Maven com.fasterxml.jackson.core:jackson-databind.2.13.1' to classpath

enter image description here

And when I click it, it adds the jackson-databind dependency in the pom.xml at this modul. So in this case it seems that classpath refers to the pom.xml, not an environment variable. Are these different types of classpath? And why my projects are working properly without having the classpath environment variable? Thank you!

CodePudding user response:

The IDE puts 'Maven Dependancies' on the class path.

When a jar is built for deployment Maven puts all the listed dependencies in the jar file it builds. Java knows how to read this info and put the right locations on the classpath.

The locations of jars are listed in the META-INF\MANIFEST.MF

Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.2.2
Build-Jdk-Spec: 11
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.altron.ne.SpringBootApp
Spring-Boot-Version: 2.7.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx

In this case (Spring Boot application) the dependency jars are all in BOOT-INF/lib/ within the main jar file.

CodePudding user response:

The classpath is a feature of the JVM (actually: the built-in ClassLoaders) that allows you to specify where Java (without any extensions) should load classes from: a list of .jar files that contain classes and a list of directories that contain classes.

When you start a Java application with

java -jar yourapp.jar

the classpath (as defined either through the environment variable "CLASSPATH" or through the command line argument "-cp") is ignored.

Instead of that, Java reads the file "META-INF/MANIFEST.MF" and uses two attributes from that file:

  • Class-Path contains the list of jar files and directories to read class files from
  • Main-Class contains the name of the class that contains the public static void main(String... args) method

Spring Boot is a special case because it brings its own ClassLoader implementation that loads additional classes not from Javas classpath.

In a Spring Boot application only the "Main-Class" attribute is set, meaning that only classes directly contained in the jar are on the classpath. Among these classes is a Spring Boot specific ClassLoader (the LaunchedURLClassLoader) and it is this special ClassLoader the interprets the "Spring-Boot-Classes" and "Spring-Boot-Lib" attributes.

Using this method allows Spring Boot to package all dependencies into a single "yourapp.jar" file - something that Java doesn't support out-of-the-box.

  • Related