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.
Related
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?
I have just shifted back from an IDE to Notepad to write a Java program. The program is using 20 JARs. I compiled successfully. When I decided to run the Java class file using
java -cp ".\\*" MyProgram
it was giving the standard error "Couldn't find or load main class....".
I was confused because when I used to run the java command with all files in an existing folder, it would just get those JARs as the current folder is already in the classpath. As the program is running from the current folder, I tried using -cp "." to include it explicitly in the classpath but that didn't work either.
Finally I was able to run the program with this command:
java -cp ".\\*;." MyProgram.java
I am asking this question to understand the actual logic behind Java's classpath.
Correct me if I am wrong, but I think that the JAR is just a standard archive in which all the packages are encapsulated in respective folders. If all the JARs are in my current folder including my main class file then why can't I run it with:
java -cp "." MyProgram
or simply:
java MyProgram
If the problem is with the multiple JAR files to include and that's why we used ".\\*" to include all the JARs in the classpath, then why do we have to explicitly include the current folder again in the classpath using:
java ".\\*;." MyProgram
To include all jar required to run your program in command prompt use wildcard *:
java -classpath E:\lib\* HelloWorld
You are using "." that defines current directory and "./*" defines all files in current directory.
The class path is a list of jar files and directories containing the classes and resources of your program. Mentioning a jar file adds its contents to the class path.
"./*" will get you only the jar files in the current directory, "." adds the current directory to the class path. This allows to access all classes (and the jar files as raw file resources but not its contents, i.e. the classes contained in them).
If you need both in the class path, you have to specify both.
You've answered your own question, sort of.
. means that it will look for .class files in the current directory.
JARs act just like a directory. So to have the abc.jar "directory" you would specify abc.jar in your classpath.
If you need both the .class files present in the current directory, and the .class files packaged into JARs found in the current directory, you would have the following classpath: -cp ".:*.jar
All the answers here are telling you to use the wildcard without extension (* or ./*) but this is a bad practice, you don't want Java to go look into irrelevant files, so specify the extension: *.jar.
"." means current directory not files in the directory
"./*" means all files in current directory.
So you want to use all jars in current directory so 2nd will work
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)
I have a question around addition of specific jars from a specific folder.
Scenario:
I have a lib folder which contains a number of jar files. Due to some issue, I have to give preference to a jar file over others.
Refer this issue: http://bugzilla.slf4j.org/show_bug.cgi?id=327
Now am trying to put a specific jar file to be loaded first here log4j-1.2.17.jar
One option is I simply hardcode this in my app script to make sure this jar is always added firstly in the classpath.
Problem in the approach:
Since the project is maven based, there is a chance that log4j version changes. And in that cases I am prone to same issue again, as I have to go and change the version in the script too.
Other option (for which I am searching the solution), there is some possibility like:
Example command (Expected, but this is not working though):
java -cp <path to my app>/lib/log4j*:<path to my app>/lib/* MainClass
The advantage I see here, even if log4j version changes, I will not have to change the script.
Need inputs how can I achieve approach 2?
Thanks
According to this: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
Class path entries can contain the basename wildcard character , which is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR. For example, the class path entry foo/ specifies all JAR files in the directory named foo. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.
So "*" is equivalent to all *.jar files in a directory. Maybe you could put the log4j in a lib/log directory? The following is working for me under Windows:
java -cp "lib\*;lib\log\*" MainClass
Say I have a class TreansferBook that is part of org.cadenhead.library package
I read that Java 2 SDK and Java Tools looks for packages in:
1 The org\cadenhead\library subfolder of where the java command was entered
First question is, in Eclipse, where is the option to modify where the java command was entered?
I don't even know how u would do it on the command line; would it be like
C:> cd
Would directory be the workspace and project directory? And are packages in side this direcytory
C:\\ java org\cadenhead\library
2 The org\cadenhead\library subfolder of any folder in your ClassPath setting
I know the classpath tells the jvm where classes and packages are located. Again, as I asked above, is this a subfolder of workspace/project/?
3 The org\cadenhead\library subfolder of a java archive fil (JAR) in your Classpath
Finally, what is this?
When using an IDE like eclipse, you don't set anything. The IDE already knows where your code is and can set the classpath appropriately. This is not something you need to worry about, it's one of the perks of using an IDE.
Where java is run from is not important. What is important is that the classpath for the java command is set to contain the root directory of your class files (the parent of /org in your case) and any dependent jar file you may have.
Some things to about class loading and Eclipse:
The JVM (and the compiler) look for classes in every directory and in every JAR file listed on the CLASSPATH. For example, if you have a class path like: CLASSPATH=c:\workspace\myproject;some_library.jar, then the VM will look for a class org.cadenhead.library.SomeClass in
c:\workspace\myproject\org\cadenhead\library
In the directory org\cadenhead\library contained in the JAR file.
In Eclipse, the default directory on the classpath is the "bin" directory inside your workspace, plus all linked projects and JAR files.
The location from which the "java" command was called is the project directory itself.