Search code examples
javajakarta-eeantjvmjavac

Why if I try to execute a class containing the main() method from within its package I obtain an error message?


I have a Main class containing the main() method declared into a package named mainPkg.

Now I use an ANT script to perform the compilation with Javac, this tartget:

<target name="compile" depends="clean">

    <mkdir dir="build/classes"/>

    <echo>INTO compile TASK</echo>
    <echo>BASE DIR: ${basedir}</echo>
    <echo>CLASSPATH: ${basedir}\lib\ojdbc6.jar</echo>

    <javac srcdir="src/mainPkg/" destdir="build/classes">

        <classpath>
            <fileset refid="classpath.compile"/>
        </classpath>

    </javac>
</target>

Ok it works and it create the compiled Main.class file inside this directory (situated in the project root): build/classes/mainPkg/ (the last directory have the package name)

Ok, now my doubt is: why if I go into build/classes/ folder and here I perform:

java mainPkg.Main

it works, infact I obtain this output (at certain times there is an exception but this is another problem not related at what I am asking at this time):

C:\Projects\edi-sta\build\classes>java mainPkg.Main
Hello World !!!
0
java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at mainPkg.Main.main(Unknown Source)

But if I enter into the build/classes/mainPkg/ directory (the package) it don't works and I obtain an "impossible to find or load main class" error message?

Infact:

 Directory di C:\Projects\edi-sta\build\classes\mainPkg

12/02/2015  17:39    <DIR>          .
12/02/2015  17:39    <DIR>          ..
12/02/2015  17:39             1.190 Main.class
               1 File          1.190 byte
               2 Directory   8.091.906.048 byte disponibili

C:\Projects\edi-sta\build\classes\mainPkg>java Main
Errore: impossibile trovare o caricare la classe principale Main

Can you explain me why it happens?

Tnx


Solution

  • If you notice in your source file, there's a package statement for Main.java like this

    package mainPkg;
    public class Main{
    
    }
    

    When you're compiling, you're saying that my Main class has a namespace called mainPkg. Now that you defined a namespace for your class any attempt to access Main should have the namespace prefix like mainPkg.Main which we usually refer to as Fully Qualified Class Name.

    When you're in build/classes and invoking java mainPkg.Main, JVM will first check if there's a mainPkg sub-folder in the current directory. As it's there already it goes inside and finds the Main, verifies if the fully qualified class name matches with what we gave in java command, if it's same it'll load your class and execute your main().

    When you're running the same java mainPkg.Main from build/classes/mainPkg, this time there's no sub-folder called mainPkg within mainPkg, so it will throw the error that you're seeing.

    Hope this makes sense :)