As we know that the package
statement is when triggered by the javac
command, it creates the related directories according to the package name.
For example:
// MyClassB.java
package abc.xyz;
class MyClassA{
// ...
}
class MyClassB{
// ...
}
Now when I compile this file:
javac -d . MyClassB.java
After compilation, we will have the following directory structure having the .class
files.
/
|___ abc
|___ xyz
|___ MyClassA.class
|___ MyClassB.class
Now the question is that, are these MyClassA.class
and MyClassB.class
contains only the MyClassA
and MyClassB
class's compiled bytecode?
What about the following statement?
package abc.xyz;
Is that statement removed during the compilation? Or this statement is only removed from the MyClassA
class and remains in the MyClassB
class because the name of the file was MyClassB.java
. Or maybe the MyClassB.class
file only contains the MyClassB
class bytecode after compilation and the package abc.xyz;
is removed during the compilation as well? If package abc.xyz;
is not removed at the compilation time then it would be the problem when we will use this file at runtime because the runtime engine will also trigger the package abc.xyz;
statement bytecode version, so, it would be a problem. Or it is removed during the compilation? Or the bytecode is only created for the classes but not for the file which contains the package abc.xyz;
statement which results that package abc.xyz;
is not become the part of the .class
files.
The picture below clearly explains the question:
Can anyone explain what is the scenario behind this? It is my humble request to the contributors to not negative mark my question because i have some confusions regarding java, so, i want to clear my concept.If still my question is able for negative mark, then its Ok do, but at least answer as well.
Thanks !!!
Directives like the package
declaration, as well as import
statements, do not generate any code at all, they only affect how the compiler will treat names within the same compilation unit.
So a declaration like
package abc.xyz;
public class MyClassA {
}
creates a class with the qualified name abc.xyz.MyClassA
or a class with the simple name MyClassA
within the package abc.xyz
; both means the same.
The qualified name is stored within the .class
file, which is the only relevant information to the JVM.
There is the convention to store such file as SimpleName.class
within a directory derived from the package name, i.e. abc/xyz/MyClassA.class
, adhered by javac
and used by the standard class loaders to look up the file when a class of that name is requested. Obviously, having such a convention makes life easier.
In principle, other storage methods are possible and there are some known. Starting with Java 9, the reference implementation has a module image format, before that, there was the “shared class data archive”, further, there was “Pack200”, an archive format that has been deprecated for removal with JDK 11.
Note that even jar files, which are extended zip files, are not exactly what you see. A zip file consist of a linear sequence of file entries having a qualified name, so in your case, you would have two entries reporting their names as abc/xyz/MyClassA.class
and abc/xyz/MyClassB.class
, whereas any directory structure shown by tools is actually derived from these names and does not implies that nested entries for abc
and xyz
actually exist. Still, the standard class loader will also use these entries the same way as if this directory structure existed, so there is no problem with the mindset of having stored the directory structure into the zip/jar file.
But starting with Java 9, there can be different versions for the same class, to be selected depending on the current Java version. The naming scheme used for that is not part of the convention used by javac when storing the files.