question about how javac finds referenced files.

Hi

I am just beginning to learn Java and have got some questions related to packages.

I have two classes:

*********************************************

MyClass.java

package pkg;

public class MyClass {

public void prn(int x){

System.out.println("Integer: "+x);

}

}

**********************************************

**********************************************

Test.java

-

import pkg.*;

public class Test{

public static void main(String[] args){

MyClass obj=new MyClass();

obj.prn(2);

}

}

*********************************************

Directory structure

/root/ jprog/MyClass.java

/root/ jprog/Test.java

Executing the following sequence of commands gives me:

# ls

MyClass.java Test.java

# javac -d . MyClass.java

# ls

MyClass.java Test.java pkg/

# cd pkg

# ls

MyClass.class--compiles.

# cd ..

# javac Test.java

Test.java:5: cannot access MyClass

bad class file: ./MyClass.java

file does not contain class MyClass

Please remove or make sure it appears in the correct subdirectory of the classpath.

MyClass obj=new MyClass();

^

1 error

Now after reading another thread on this forum I came to know that the compiler finds the

MyClass.java in the wrong package. Using verbose option with javac shows this.

So I move it to some other directory and everything works.

# mv MyClass.java /root

# ls

Test.java pkg/

# javac Test.java

# java Test

Integer: 2

#

Now the question begins:

Suppose we go back to how the files were arranged before I moved the MyClass.java file and

I change the Test.java file by adding

package pkg2;

statement to it.

Now everything compiles

# ls

MyClass.java Test.javaI have deleted pkg and .class files

# cat Test.java

package pkg2;

import pkg.*;

public class Test{

public static void main(String[] args){

MyClass obj=new MyClass();

obj.prn(2);

}

}

# cat MyClass.java

package pkg;

public class MyClass {

public void prn(int x){

System.out.println("Integer: "+x);

}

}

# javac -d . MyClass.java

# javac -d . Test.java

# ls

MyClass.java Test.java pkg/ pkg2/

# java pkg2.Test

Integer: 2

Why isn't the MyClass.java file causing any problems now?

Using the verbose option with javac shows that the compiler goes straight for the pkg/MyClass.class.

My readings of Core Java Horstmann tell me that the compiler always looks in the current directory. javac documentation also doesn't help. I know that the documentation recommends that the source file locations should match the package statements.

I'm just trying to learn how javac finds referenced files.

Any help?

Thanks a load in advance.

[3046 byte] By [java_nu_bea] at [2007-11-27 4:13:03]
# 1

> I know that the

> documentation recommends that the source file

> locations should match the package statements.

This is not merely a recommendation, it is a requirement.

Both javac and java find classes by traversing the classpath. The classpath should contain directories (or jar files) that correspond to the top of a (part of the) package hierarchy.

For example, if the Java code for your class is in a file C:\src\pkg\MyClass.java, and MyClass.java declares the class to be in package pkg, the classpath should contain C:\src. Classes are then found by transforming their package declaration into a directory structure.

Please note that javac works on *files*, not classes. Therefore it is necessary to specify the full filenames of the files you want to compile, even if you have specified the classpath. By default, javac will put compiled class files in the same location as their sources, so the classpath for the java command should also contain C:\src.

The exception to the rule is when all classes for the program are in the default package (i.e., they do NOT contain a package statement). In that case, it is possible for javac (and I believe java as well) to find all classes in the current directory, so it will "just work".

You can specify the classpath using the -cp parameter to both javac and java.

Hope this helps.

Herko_ter_Horsta at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 2

Thanks for the reply.

> > I know that the

> > documentation recommends that the source file

> > locations should match the package statements.

>

> This is not merely a recommendation, it is a

> requirement.

Correct me if I'm wrong I don't think that is necessary for source files.

> Please note that javac works on *files*, not classes.

Yes, I do understand that. I typed that in a hurry and copy pasted it in the last line(lazily)

What I would really like to know is that: how javac goes about finding referenced classes when there is a package statement in the source file one is compiling and when such a statement is not present?

I think knowing this will help me sort out the issue I'm facing.

Thanks again.

java_nu_bea at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 3

> Thanks for the reply.

>

> > > I know that the

> > > documentation recommends that the source file

> > > locations should match the package statements.

> >

> > This is not merely a recommendation, it is a

> > requirement.

>

> Correct me if I'm wrong I don't think that is

> necessary for source files.

>

You are wrong.

cotton.ma at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 4
Yeah! surethanks
java_nu_bea at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 5

> > Thanks for the reply.

> >

> > > > I know that the

> > > > documentation recommends that the source file

> > > > locations should match the package statements.

> > >

> > > This is not merely a recommendation, it is a

> > > requirement.

> >

> > Correct me if I'm wrong I don't think that is

> > necessary for source files.

> >

>

> You are wrong.

Is that new? I know that as of, oh, 1.2-ish or so, source file directory trees did not have to match the package structure. It'd've been stupid not to do so, but the compiler didn't require it.

jverda at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 6

Suppose I have two files in unix account root

/root/ jprog/MyClass.java

/root/ jprog/Test.java

//MyClass.java

package pkg;

public class MyClass {

//...

}

//Test.java

import pkg.*;

public class Test{

public static void main(String[] args){

MyClass obj=new MyClass();

}

}

I compile MyClass using (pwd=/root/jprog)

# javac -d . MyClass.java

compiler creates MyClass.class in /root/jprog/pkg

Now I try and compile Test.java with

# javac Test.java

I get

Test.java:5: cannot access MyClass

bad class file: ./MyClass.java

file does not contain class MyClass

Please remove or make sure it appears in the correct subdirectory of the classpath.

MyClass obj=new MyClass();

^

1 error

using verbose tells me that the compiler went looking for MyClass found MyClass.java parsed it and exited with the above error message. I remove MyClass.java and everything works.

Now if I add a statement like

package pkg2;

to Test.java the compiler goes straight for the MyClass.class file and MyClass.java doesn't cause any problem.

Whats happening here?

java_nu_bea at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 7
Why don't you just follow the advice and put your code in a directory structure that matches the package structure?It helps avoid this kind of errors and questions which have nothing to do with the actual problem your code is supposed to solve.
Herko_ter_Horsta at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 8

as I see it I have these options:

either manipulate classpath on command line for each source file that Icompile using javac so that it goes about finding referenced classes in places that I want it to do and doesn' t complain when it finds source files in "wrong" locations.

organize source files in a directory structure matching.....

hide all this behind an IDE

But that still leaves my original question unanswered.

How can I go about reading the source code for javac that comes with sun's jdk? Any references that any body can suggest?

Thanks

java_nu_bea at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...
# 9

If you order your code the correct way, you will only have to specify one classpath and Java(c) will be able to figure out where your classes and source files are, without having to specify a different classpath for each class you wish to compile.

The OpenJDK project will probably have the source code for the javac tool. http://openjdk.dev.java.net/

Herko_ter_Horsta at 2007-7-12 9:19:10 > top of Java-index,Java Essentials,Java Programming...