-sourcepath vs -classpath - java

Studying for the oracle certification I am trying all the possible scenarios that might occur during the exam.
For example, here there is a little doubt about shell command line (unix based):
Let's imagine there is a folder called myProject and a sub folder called myProject/source.
File SubFile.java is in the folder myProject/source and another file File.java is in myProject folder.
By typing the following commands I get to different behaviors:
cd source (therefore, currently I am on "myProject/source")
javac -sourcepath ../ File.java
// The command ../ does not work to access "Folder"
then after compiling File.java from myProject folder and returning to the sub Folder if I try:
javac -classpath ../ SubFile.java
// with the flag -classpath it seems to accept the ../ syntax to access the super folder.
Do you know why it works like this? and moreover is there any chance to access the super folder with the -sourcepath flag?

It depends on whether SubFile also references File.
Consider the following code:
public class SubFile {
private static File file = new File();
}
Assumed that this file is located in your source folder, and assumed that you are in the source folder, then
javac -sourcepath ../ SubFile.java
will compile SubFile.java into SubFile.class inside the source folder, and will compile File.java into File.class in the parent folder. If there is no dependency between those files, then the compiler will not compile File.java (means, the compiler will not automatically compile all files on the sourcepath).
When compiling with -classpath, then the classpath is also searched for source files, unless you explicitly specify a separate sourcepath - in the following case, the compiler will throw an error (assumed that you have cleaned the File.class file before):
javac -classpath .. -sourcepath \temp SubFile.java
See also javac - Java programming language compiler and Differences between classpath and sourcepath options of javac for more information.
The important point from these two links is:
Note: Classes found through the class path may be subject to automatic recompilation if their sources are also found.

Related

Java command terminal

Alright so i am trying to run my java file but it's not doing what I want it to from terminal.
I have a main directory called packageTester.
packageTester contains src and bin
src has packageA packageB
pacakgeA has HelloA.java
packageB has HelloB.java
bin has my class files so
bin has packageA packageB
pacakgeA has HelloA.class
packageB has HelloB.class
To compile the files I used the following command when I was in the pacakageTester directory:
javac -d bin -sourcepath source src/package*/* , which works !
Now how do I run HelloB.class which contains the main method and has an object of HelloA.
I thought when at the packageTester directory, I can do:
java bin/packageB/HelloB
but that does not work because it cannot seem to find the .class file.
HELP will be greatly appreciated to figure out how to execute the file correctly
The root of bin should be in your classpath in order for packageB.HelloB to be found as packageB/HelloB.class while parsing the classpath.
The easiest way to do so is to change directory to bin and execute java packageB.HelloB from there.
Alternatively, you can execute java -cp bin packageB.HelloB from your packageTester directory, or from somewhere else if you replace bin by an absolute path.

Compiling a java file using javac and the command line

I am trying to learn more about javac and how to use developer tools for Java using the command line.
As far as I understood, the option -classpath is needed to specify the path where javac searches for our classes and resource files, if we are not in the current directory, because usually the class path is set to our current working directory.
This is my current working directory:
/Users/user1/Desktop
And I am trying to compile a .java file which is in:
/Users/user1/Desktop/PF/
and the file is called MainClass.java.
I am trying to compile it using the following command:
javac -classpath /PF MainClass.java
But it does not seem to work, in fact I keep receiving the following:
javac: file not found: MainClass.java
Usage: javac <options> <source files>
use -help for a list of possible options
What am I doing wrong?
Classpath is for .class files, not for .java files.
javac command needs correct path to the .java file to compile it. So
javac ./PF/MainClass.java
Will create the class file in current directory.
If your MainClass.java depends on any class files to compile correctly, then you put those class/jar files in classpath.
That isn't how the classpath works. You use the classpath to point to classes that your Java file needs in order to compile. You don't use the classpath to point to the Java file itself.
Either go into the PF directory and do this:
javac MainClass.java
That will create the MainClass.class file inside the PF directory. If instead you want to create the MainClass.class file on your desktop, then from your desktop, do this:
javac PF/MainClass.java
-classpath
Specifies the path javac uses to look up classes needed to run javac
or being referenced by other classes you are compiling. Overrides the
default or the CLASSPATH environment variable if it is set.
Directories are separated by colons. It is often useful for the
directory containing the source files to be on the class path. You
should always include the system classes at the end of the path.
class path is used to specify the compiled sources that need to be used in your class. For example in this code if you are accessing another class then you should specify the location of the compiled sources of the that class.
In your case if don't have any class dependency then simply remove classpath option and compile using[navigate inside folder]
javac Mainclass.java
Remove the -classpath. And if you are in the place where the java file is required (which currently you arent) you can remove that PF/ too.

Is it possible to use relative path when compiling the java files?

Hi I am trying to learn to compile a java class with make file. My make file looks like this:
build:
javac test_java.java
clean:
rm -rfv *~ test_java.class
run:
java test_java
Now I have moved the test_java.java into a folder, called classes I am trying to compile the file using a relative path, is it possible?
I have tried:
javac -d classes test_java.java
but I am getting errors:
javac -d classes test_java.java
javac: file not found: test_java.java
Usage: javac <options> <source files>
use -help for a list of possible options
I have also tried: -d ./classes and also -d /home/the/whole/path (but I would like to have the relative path), and the errors are the same. It seems to work only the
javac classes/test_java.java
What am I doing wrong?
Update: The original answer here was completely wrong. You must specify the path to your source files. -sourcepath is for another purpose:
Specify the source code path to search for class or interface
definitions. As with the user class path, source path entries are
separated by semicolons (;) and can be directories, JAR archives, or
ZIP archives. If packages are used, the local path name within the
directory or archive must reflect the package name.
Note that there are many other build tools for Java applications that are very mature and well regarded. Maven, Gradle, and Ant are the ones that spring to mind immediately. If you don't have to use make I would take a look at one of those.

java compiling from the command line

I am an experienced programmer, but haven't used Java in years - mostly C# - and used an IDE in the past. I'm trying to compile some code from the command line on my Mac, but can't get my test file to find my source code. I'm assuming the problem lies somewhere in the space of packages, file structure, classpaths, and import statements - but I've put a couple hours in (including hunting on Stack Overflow) and am still stuck.
Here's what I have:
Directory structure:
ProjectName
|
--src
|
--SourceClass
--test
|
--SourceClassTest
--external
|
--testng-6.8.7.jar
My SourceClass looks like this:
package ProjectName;
public class SourceClass<T>{
}
Very simple. Obviously, there will be more - but I wanted to start with making sure I had all this setup stuff correct before I actually did coding.
My test class looks like this:
package ProjectName;
import java.util.*;
import org.testng.Assert;
import org.testng.annotations.*;
public class SourceClassTest{
#Test
private void createEmptySourceClass(){
SourceClass<Object> sourceClass = new SourceClass<Object>();
Assert.assertTrue(sourceClass.isEmtpy());
}
}
The sourceClass compiles with no issue with "javac src/*.java", run from the "ProjectName" directory. I want to see this fail with an error along the lines of "SourceClass doesn't have an isEmpty() method", but instead I run javac like this from the "ProjectName" directory:
javac test/*.java -classpath external/testng-6.8.7.jar
and get this exception:
test/SourceClassTest.java:12: error: cannot find symbol
SourceClass<Object> tree = new SourceClass<Object>();
^
symbol: class SourceClass
location: class SourceClassTest
test/SourceClassTest.java:12: error: cannot find symbol
SourceClass<Object> sourceClass = new SourceClass<Object>();
^
symbol: class SourceClass
location: class SourceClassTest
2 errors
I've tried a lot of things -adding an import statement, adding a sourcepath to the javac command, compiing the sourceClass as a jar and putting it in the bin directory then adding that to the classpath, but I can't get the test to find the SourceClass symbols.
Any idea what I am missing here?
It works if you compile into a separate target directory. E.g,
mkdir target
javac -d target/ src/*.java
javac -classpath target/ test/*.java
When you do javac src/*.java, it will create the .class file in the src directory itself. By default, any classes you reference are assumed to be in the same package. So even if you add src/ to the classpath, it looks for src/ProjectName/SourceClass.class, which it does not find. When you pass the -d target/ option, it creates the proper package hierarchy, so and finds the class.
Relevant documentation from the javac official doc:
You should arrange source files in a directory tree that reflects
their package tree. For example, if you keep all your source files in
C:\workspace, the source code for com.mysoft.mypack.MyClass should be
in C:\workspace\com\mysoft\mypack\MyClass.java.
By default, the compiler puts each class file in the same directory as
its source file. You can specify a separate destination directory with
-d (see Options, below).
...
...
-d directory Set the destination directory for class files. The directory must already exist; javac will not create it. If a class is
part of a package, javac puts the class file in a subdirectory
reflecting the package name, creating directories as needed. For
example, if you specify -d C:\myclasses and the class is called
com.mypackage.MyClass, then the class file is called
C:\myclasses\com\mypackage\MyClass.class. If -d is not specified,
javac puts each class files in the same directory as the source file
from which it was generated.
Note: The directory specified by -d is not automatically added to your
user class path.
My guess is it can't find SourceClass because the file defining that class is under src, and you didn't mention that directory in your javac command line.
If I were you, I would change the file hierarchy to this:
ProjectName/src/ProjectName/SourceClass.java
ProjectName/src/ProjectName/SourceClassTest.java
ProjectName/external/testng-6.8.7.jar
Then run javac src/ProjectName/*.java -classpath external/testng-6.8.7.jar.
Or keep the file hierarchy the way it is, and run javac src/*.java test/*.java -classpath external/testng-6.8.7.jar
The accepted answer is correct, but it misses one critical point: when javac is asked to compile *.java (as opposed to foo.java, and then foo2.java ...) it treats them as a single package and accepts references between them.
That's the magic. Other languages do this less implicitly with header files.
Even after reading this post, it took me some time to figure that out, against my inherent assumption that a program running singly on files one after the other would (should) produce the same result as running that program on a group of files. My bad; the * is NOT a mere convenience, but critical.

Package not found; javac

This is annoying.
I have a directory structure like this
-lib
--some jar files
-packageName
--Main.java
--SomeOtherPackage
--SomeOtherJavaClass.java
Main.java imports SomeOtherPackage. And both java files uses jars in the lib.
What I do is add the jar files independently in the CLASSPATH. And then run as:
javac packageName/Main.java
but it gives the error that Package not found SomeOtherPackage . Shouldn't it automatically realize the dependency and build SomeOtherPackage as well? What would be the javac command and the classpath for the above case?
Thanks
The normal practice is to add the package root to the classpath.
When you're already in the package root, use -cp .. E.g.
cd /path/to/all/packages
javac -cp . packageName/Main.java
If you want to include JAR files as well, use the ; (or in *nix, the :) as classpath path separator:
javac -cp .;lib/file.jar packageName/Main.java
To save the time in repeating all the typing of shell commands, use a .bat (or in *nix a .sh) file. Or just an IDE if you're already familiar with java/javac and so on.
You need to add packageName to the CLASSPATH so it can find SomeOtherPackage

Categories

Resources