I am using web application in which jar files are there in lib folder. In web.xml, servlet class is provided.how does web.xml knows in which jar file that specific class is there???
This is handled by the classloader mechanism:
A JAR file usually contains a "manifest" -- a file which lists the
contents of the JAR. The manifest can define a JAR-class-path, which
further extends the class path (but only while loading classes from
that JAR). Classes accessed by a JAR-class-path are found in the
following order:
In general, classes referenced by a JAR-class-path entry are found as
though they were part of the JAR file. The JAR files that appear in
the JAR-class-path are searched after any earlier class path entries,
and before any entries that appear later in the class path. However,
if the JAR-class-path points to a JAR file that was already searched
(for example, an extension, or a JAR file that was listed earlier in
the class path) then that JAR file will not be searched again. (This
optimization improves efficiency and prevents circular searches.) Such
a JAR file is searched at the point that it appears, earlier in the
class path. If a JAR file is installed as an extension, then any
JAR-class-path it defines is ignored. All the classes required by an
extension are presumed to be part of the SDK or to have themselves
been installed as extensions.
source
The magic word in this case is class path .
The book "Learning in Java" describes this nicely.
https://www.safaribooksonline.com/library/view/learning-java/1565927184/ch03s03.html
Java CLASSPATH variable, holds a list of locations that can be searched for packages containing Java class files. The Java interpreter and Java compiler use CLASSPATH when searching for packages and classes on the local host.
Just like we add directory location to path variable in dos/linux we can specify the location of jars in classpath variable.
Java also provided some default locations that it will look in. For example the ext directory. The path of ext folder in java on a windows installation may look like "C:\Program Files\Java\jdk1.6.0\jre\lib\ext" .
You can put your jars in the ext folder and class files in them will be automatically located..
A location on the class path can be a directory name or the name of a class archive file. Java supports archives of class files in its own Java archive ( JAR) format . This allows large groups of classes to be distributed in a single file; the Java interpreter automatically extracts individual class files from an archive,when required.
The Java interpreter knows how to find core classes, which are the classes included in every Java installation. For example , the classes in the java.lang, java.io etc. Their location need not be put in class path, the Java interpreter can find them by itself.
To find other classes, the Java interpreter searches the locations on the class path in order.
For example consider a search for the class vehicle.cars.Porche. Searching the class path directory /usr/lib/java means the interpreter looks for an individual class file at /usr/lib/java/vehicle/cars/Porche.class. If the class is present in a jar file say CompanyVehicle.jar then the compiler will be looking for vehicle.cars.Porche.class in the CompanyVehicle.jar.
To sum it up , Java has a list of location it knows it should look into. Other than that, it will look into locations you provide in classpath variable.
if you want to understand more about how classpath, classloaders work behind the scene check out the links below
How JVM starts looking for classes?
http://javapapers.com/core-java/java-class-loader/
https://en.wikipedia.org/wiki/Classpath_(Java)
Related
can someone tell me please what are the difference between Rsrc-class-Path and Class-Path sections of a runnable-jar's mannifest file?
Now I take them as granted as generated by Eclipse, but I'd like to understand how it works.
What I think based on how Eclipse generates code seems that the first is about jars my app needs, the second is always .. But I have no clues what folder . refers to.
The Class-Path attribute. This is a standard attribute defined by the JAR file specification. It contains a list of relative URLs for that will be included on the runtime classpath when you run the JAR using java -jar ....
This provides a way to add external JARs (and directories) to the runtime classpath. The entries must be relative, and are resolved relative to the directory containing the main JAR. (For security reasons ...)
The Rsrc-class-Path attribute is non-standard. This is used by Eclipse's "jars-in-jar" launcher. A typical manifest looks like this:
Manifest-Version: 1.0
Rsrc-Main-Class: com.abc.Master
Main-Class: com.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
Rsrc-Class-Path: ./ lib/xyz.jar
where com.abc.Master is your apps (real) main class, and lib/xyz.jar is a relative URL for a JAR file that is nested within this JAR.. You will also see that the JAR contains the ".class" file for JarRsrcLoader.
This is what happens with you run java -jar this.JAR arg1 arg2.
The JVM is created
The JVM jar loader opens the JAR, reads and parses the MANIFEST.MF above.
It loads the JarRsrcLoader class given by Main-Class/
It calls the above classes main method, passing it ["arg1", "arg2"]
The JarRsrcLoader examines the manifest, and extracts the Rsrc-Class-Path and Rsrc-Main-Class.
Then JarRsrcLoader creates a special classloader that knows how read JARs embedded within the current JAR. The classpath for this classloader is "./" follows by "lib/xyz.jar", where these URLs are resolved within the outer JAR file.
Then JarRsrcLoader loads the class com.abc.Master using the special class loader.
Then JarRsrcLoader calls the main method for com.abc.Master, passing the same string array containing the arguments.
Finally, the application runs.
In short, Rsrc-Class-Path is an attribute that the JarRsrcLoader class understands, and uses to construct the actual application classpath.
In this context, the Class-Path: . attribute serves no real purpose. Everything needed to run JarRsrcLoader will be in the JAR.
As a final note, the SpringBoot loading mechanism is similar, but it uses a different non-standard attribute for the application's main class, and puts the application's resources (e.g. JARs) into a particular directory ("/boot-inf") within the main JAR.
I came across this question:
What is a classpath and how do I set it?
and the first answer explainns what classpath is and how to set it:
.....First, let's suppose that MyClass is something you built as part of
your project, and it is in a directory in your project called output.
The .class file would be at
output/org/javaguy/coolframework/MyClass.class (along with every other
file in that package). In order to get to that file, your path would
simply need to contain the folder 'output', not the whole package
structure, since your import statement provides all that information
to the VM.
Now let's suppose that you bundle CoolFramework up into a .jar file,
and put that CoolFramework.jar into a lib directory in your project.
You would now need to put lib/CoolFramework.jar into your classpath.
The VM will look inside the jar file for the org/javaguy/coolframework
part, and find your class.
So, classpaths contain:
JAR files, and Paths to the top of package hierarchies....
but if java only looks for classes in directories specified by CLASSPATH variable how does java find classes from libraries that are part of JRE?
For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:
...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...
When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.
I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?
After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).
Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application
If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:
Class Path Wild Cards
Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').
....
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.
What happens, if there is a manifest Class-Path entry for a jar which doesn't exists at the location, but is available by another means (in the lib-folder of application server for example)
Will the unresolved Class-Path entry cause any errors?
JVM loads & searches classes in following order:
Bootstrap classes - Classes that comprise the Java platform, including the classes in rt.jar and several other important jar files.
Extension classes - Classes that use the Java Extension mechanism. These are bundled as .jar files located in the extensions directory.usually $JAVA_HOME/lib/ext directory.
User classes - Classes defined by developers. Location of these classes using the -classpath option on the command line or by using the CLASSPATH environment variable.
If the JAR-class-path points to a JAR file that was already included (for example, an extension, or a JAR file that was listed earlier in the class path) then that JAR file will not be searched again. (This optimization improves efficiency and prevents circular searches.) Such a JAR file is searched at the point that it appears, earlier in the class path.
To verify this, I also did following test
1. Created lib(jar) "classpath-test" containing a Util class.
2. Created another lib(jar) i.e wrapper-lib which uses classpath-test's Util class.
3. In wrapper-lib's MANIFEST.MF, added below entry.
Class-Path: lib/classpath-test.jar
Copied classpath-test.jar under lib dir and ran below command
java -jar wrapper-lib.jar
Above command Ran fine. Ran same command after deleting lib/classpath-test.jar, and it failed.
Another test, deleted classpath-test.jar from lib & copied in JAVA_HOME/lib/ext and ran
java -jar wrapper-lib.jar
It worked.
I have some classes in Eclipse which cannot be resolved to a type. I know that classes can be in .class, .jar, .par, .zip files. Are there any other file types that I have to look for? Or is there anything eclipse how I could make Eclipse recognize the classes?
In my general understanding, once I have found these files and added them to the classpath, the Eclipse should be able to recognize them.
Actually my colleague gave me an answer:
If the class cannot be found or resolved to a type within Eclipse, this is only the problem with build path. And to the build path, the files should be added of type as I have said: class, jar, par, zip; no other suffix is accepted.
Maybe I am misunderstanding your question, so please excuse me if I am. Type resolution errors are often due to incorrect imports or misspellings. Ill give an example:
public class Foo extends Component{
//If you forgot to import java.awt.*; You would receive the error
"Component cannot be resolved to a type"
}
Also if you misspelled an extension you would get the same error.When you create a class in eclipse you need to create a new file for that class.
You should also post your code so we know exactly what you're talking about. I don't think your error has anything to do with the classpath. :)
Class path entry could be jar, zip or directory (source)
set CLASSPATH=classpath1;classpath2...
Class paths to the .jar, .zip or .class files. Each classpath should end with a filename or directory depending on what you are setting the class path to:
For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file.
For .class files in an unnamed package, the class path ends with the directory that contains the .class files.
For .class files in a named package, the class path ends with the directory that contains the "root" package (the first package in the full package name).
Multiple path entries are separated by semi-colons. With the set command, it's important to omit spaces from around the equals sign (=).
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.
Classpath entries that are neither directories nor archives (.zip or .jar files) nor * are ignored.