Page 1 of 1
jar file contents when there is an imported package
Posted: Sat Jul 17, 2021 8:34 am
by abashdesh
Hi,
I tried the simple A package B package example given in the book - Oracle© Certified Professional Java SE 11 Programmer I Fundamentals (Exam Code 1Z0-815).
Package structure is like this -
---A
|---a.class
---B
|---b.class
a.class imports package B and class b.
Then I created a jar file with the following command -
jar -cvf a.jar A
Then I displayed the contents of the jar file using "jar -tf a.jar" command, and I see the following -
META-INF/
META-INF/MANIFEST.MF
A/
A/a.class
How come B/b.class is not a part of the jar file when A/a.class imports it?
Also how does A/a.class runs correctly with B/b.class being a part of it?
java -cp ./A.jar A.a
Hello 1 2 3 testing...
Re: jar file contents when there is an imported package
Posted: Sat Jul 17, 2021 11:37 am
by admin
1. When you create a jar file, only those files are added to the jar that you specify in the command (i.e. either as individual files or as a part directory).
The jar command does not inspect the content of the files that you are adding to the jar. It doesn't care what import statements you have.
Since you specified directory A in the jar command, it added only A and its contents to the jar.
2. Just because a.java imports class b, doesn't mean a uses b.
If your A.a class is running fine that means, it is not really using class B.b. Try doing using class b such as by adding this line in a's main:
B.b x = null; Then it will fail.
Re: jar file contents when there is an imported package
Posted: Sun Jul 18, 2021 3:46 am
by abashdesh
Thanks very much for the answer. I tried adding B package explicitly using "jar -cvf a.jar A B" and now the a.jar has both A.a class and B.b class.
I still didn't get a failure when a.jar did not have B.b class added. Even before, I had created a reference object of b class and after your reply I also tried adding B.b x = null;
Here is the code i used on a.java class -
package A;
import B.b;
public class a {
b bobj = new b();
b x = null;
public static void main(String[] args){
System.out.println("Hello 1 2 3 testing...");
}
}
The above code prints "Hello 1 2 3 testing..." when run using following and when B.b is not added to the a.jar file -
java -cp ./a.jar A.a
Hello 1 2 3 testing...
Thanks,
abashdesh
Re: jar file contents when there is an imported package
Posted: Sun Jul 18, 2021 3:54 am
by admin
By default, java looks for class files in the current directory as well. Since you have B/b.class in your current directory, it worked. Delete b.class altogther from your folders and then run it. It will fail to run.
Re: jar file contents when there is an imported package
Posted: Sun Jul 18, 2021 8:46 am
by abashdesh
Tried multiple times -
1. Removed B directory from the current directory, but the a.jar still ran with "Hello 123 testing..." output.
2. Removed A directory and recompiled a.java (with no B directory present) and then removed re-created a.jar with only A, still it ran.
3. Only when I added the following code that does a Sysout from class b and its called from class a, then it gave me the error.
Error was received even when B was present in the current directory.
Code added, recompiled a.java and b.java and recreated a.jar -
package B;
public class b{
public static void hello(){
System.out.println("Hello from class b");
}
}
package A;
import B.b;
public class a {
b bobj = new b();
b x = null;
public static void main(String[] args){
System.out.println("Hello 1 2 3 testing...");
b.hello();
}
}
java -cp ./a.jar A.a
Hello 1 2 3 testing...
Exception in thread "main" java.lang.NoClassDefFoundError: B/b
at A.a.main(a.java:10)
Caused by: java.lang.ClassNotFoundException: B.b
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
4. Then I re-created a.jar by adding B to it and then it worked without run-time error.
Probably JVM was looking for an actual executable statement, with just adding a reference assignment statement, somehow it was till working.
Re: jar file contents when there is an imported package
Posted: Sun Jul 18, 2021 10:29 am
by admin
Right, if you have both a.class and b.class in the jar, then just putting the jar in the classpath is enough. There is no need to have b.class separately.
If you have only a.class in the jar, but B/b.class is in the current directory, then also it will work because the jvm will find B/b.class in current directory. In your original post, your code was working for this reason.
Re: jar file contents when there is an imported package
Posted: Tue Jul 20, 2021 11:20 pm
by abashdesh
Hi,
If you see points 1 and 2 above what you are saying was not the case. Failure happened only when I added a Sysout call on b class and then called it from a class. When I had only created reference of b class (and nothing else) then it was working even when -
1. B.b was removed from the current directory and also not present in the jar
Hence I was asking if creating only a reference works, but again its puzzling from where it is taking the B.b class.
Re: jar file contents when there is an imported package
Posted: Tue Jul 20, 2021 11:25 pm
by abashdesh
Apols, tried this again by removing B directory from current directory and it started giving me compilation error. So what you are saying is correct it was looking at current directory by default.