Javac vs Java within -classpath option - java

What is the difference in calling the -classpath option from javac and from java
for example:
javac -classpath MyJar.jar GetJar.java
java -classpath MyJar.jar:. GetJar
it works as well as:
javac -classpath MyJar.jar GetJar.java
java GetJar
So basically where the first -classpath related to javac needs to be there, on the other hand in the java command line it might be optional. Why? Do you know in which circumstance it would be mandatory. And more in general what is the effect of -classpath called by javac and what is the effect of -classpath called by java.
Thanks in advance.

One is the classpath used for compiling. The other is the classpath used for running. And they do not have to be the same thing. The set of classes needed for the compilation processes are all those referred to by every class being compiled. Whereas your runtime JAR could be invoking a standalone class with an empty main method and no dependencies.
Just remember that at runtime class dependencies are resolved dynamically, aka a class is only loaded when it is needed (this is a generalization, boot and system classes are always loaded).

This document contains answers for your questions
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javac.html
using -classpath every time is a very time consuming work. Instead, use environment variables (if you are dealing with a package such as Java Mail)
classpath is used for compiling. Javac is the Java Compiler, where it converts your code into byte code.
When it comes to java it is used to run your Java source file/jar.

Related

Difference between using javac<file> and java<file>

From some experienced java coders I want to ask what is difference between using
javac <filename>
java <file_name_without_extention>
And
java <filename>
They're equivalent if your source code is only a single file. The former (with the two commands) is the general way to compile and run Java source code, and it's still the correct way to compile larger projects. The latter is a new feature added in JDK 11 to make it easier to run individual files and very small programs.
From the proposal that suggested the feature
In source-file mode, the effect is as if the source file is compiled
into memory, and the first class found in the source file is executed.
For example, if a file called HelloWorld.java contains a class called
hello.World, then the command
java HelloWorld.java
is informally equivalent to
javac -d <memory> HelloWorld.java
java -cp <memory> hello.World
javac <Filename> - a java command that compiles java source files into bytecodes.
It needs an extension because you are compiling the source file.
java -cp <classpath> <Classname> - a java command that executes the compiled bytecodes.
It does not need an extension because you are merely telling it to search for the Class and its main() signature from the classpath to execute.

Does the 'java' command compile Java programs?

Most websites on the internet say:
"use the javac command to compile a .java file. Then run it using the java command"
But today I tried to run a java program without javac and I got a strange result.
Here are the contents of a file called hello.java:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Then I ran:
$ javac hello.java
Which gives me this error:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
But when I run it without the javac command, it executed without any errors.
$ java hello.java
hello world
Does the java command also compile the program? If yes, why do we need the javac command?
The version of my java is:
openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)
Prior to Java 11, to run your code you have to first compile it, then you can run it. Here's an example:
javac test.java
java test
Since Java 11, you can still do javac + java, or you can run java by itself to compile and auto-run your code. Note that no .class file will be generated. Here's an example:
java test.java
If you run java -help, you'll see the various allowed usages. Here's what it looks like on my machine. The last one is what you ran into: java [options] <sourcefile> [args] which will "execute a single source-file program".
$ java -help
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
UPDATE:
As pointed out by #BillK, OP also asked:
why do we need the javac command?
The reason we need javac is to create .class files so that code can be created, tested, distributed, run, shared, etc. like it is today. The motivation for JEP 330 was to make it easier for "early stages of learning Java, and when writing small utility programs" without changing any other existing uses.
If you are running Java 11, there is a new feature that allows single source file execution. The single source compiler is more promiscuous in terms of class name versus file name, so that is how you are able to run but not successfully compile.
If you are on a previous version of Java, then your current hello.java does not compile, because of compile errors, specifically around the class name. So there's absolutely no way that calling java hello.java compiled your code, because it does not compile.
It seems most entirely likely that you were running some previously compiled code when executing the java command.
To answer why this error is given, the class name for the file must match the file's basename.
You have two options to have this code work for the traditional javac; java sequence:
Rename the class to public class Hello or
Rename hello.java to myclass.java.
The java interpreter for Java 11 does not impose this requirement. The class that contains main can have any name, as long as it is the first class in the file. This was mainly intended to ease the learning process for beginners, and to allow "java scripting" with the shebang (ref.).
Yes, but not in the way you probably mean.
When you use the javac command to compile a .java file to a .class file the output is something called bytecode. Bytecode is a the machine code (native instructions) for a theoretical CPU based on the Java Virtual Machine specification.
This virtual CPU specification is sort of an average of types of CPUs that were common at the time the specification was written. Because of this it is close to lots of different types of CPU making it easier to run the same Java .class files on multiple CPU types.
When Java was first launched the java command would read the .class file and interpret the bytecode instructions one at a time and then map them to the equivalent native instruction for what ever CPU it was actually running on. This worked but wasn't particularly fast. To improve this Just in Time (JIT) compilation was added to the Java Runtime.
With JIT the java command takes the bytecode and compiles it again to the native instructions for the CPU it is running on. Modern Java runtimes tend to start out interpreting the bytecode while JIT compiling in the background and switch to the compiled native instructions when it's ready and will also profile the running application and then recompile the bytecode again with different optimisation to get the best possible performance.
EDIT (to appease the down voters):
So in your specific case (as you are running a JRE newer than v11) the code is compiled (at least) twice
As a single .java file to bytecode
Via the JIT compiler as it interprets the bytecode (though for helloWorld it might not actually get time to run any of the compiled native code)

Compiling packages in java at windows command line

I have trying to compile java files at the windows command line using commands such as:
java myProg once I have used javac to create class files.
Problems arise when I use packages with a number of source files.
Often but not always I get main not found errors even though a main exists.
I am not quite sure what some of the directives mean and that is why it seems hit or miss.
Question
what does -cp mean exactly? java -cp src\myDirectory.myfile
sometimes I see:
./ infront of source eg .\src\myDirectory.myfile
on other sites I have found
% javac -cp .;stdlib.jar MyProgram.java
% java -cp .;stdlib.jar MyProgram
while compiling a jar library with java source files
what doesthe ".;" mean?
basically how do I compile three java source java files in one package at the windows command line and what does -cp and .; mean?
-cp means class path if I'm not mistaken.
try reading the following java docs
-classpath path
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 semi-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. For example:
javac -classpath .;C:\users\dac\classes;C:\tools\java\classes ...
https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/tooldocs/win32/javac.html
Answering your question directly, -cp means classpath or path.
Details on commandline arguments used while compiling and running a Java application can be found here: javac - Java programming language compiler
Extracting the description of -cp from that page:
-cp path or -classpath path:
Specify where to find user class files, and (optionally) annotation processors and source files. This class path overrides the user class path in the CLASSPATH environment variable. If neither CLASSPATH, -cp nor -classpath is specified, the user class path consists of the current directory. See Setting the Class Path for more details.
. means the current directory.
To compile multiple files in a directory use the following:
javac *.java // compliles all java files in the dir
java MyClass // runs the particular file
There are also a bunch of other related questions that should help you resolve this:
How to run a java program from the command line
How do I run java program with multiple classes from cmd?
Problems running a java program from the command line interface
Can't run multiple-class program from command line using packages

Basic Java - Packaging

I decided to post this question after trying to find an answer for it, and couldn't find one.
I'm studying for OCJP and tried few simple codes. This is what I did and need to do.
Created two .java sources, say TestOne.java, TestTwo.java [using
notepad++]
Created a directory named "package1" and placed the two sources in
them.
Both the source files have "package package1;" as their first statement.
TestOne.java has one public class and one class with default access.
TestTwo.java has one default class with an object of the default
class in TestOne.java.
The main method is in this default class in TestTwo.java. It tries to invoke a method in
the referred object that was created, using TestOne.java default class.
So after all that was set up compiled TestOne.java then TestTwo.java by setting the flag "classpath" in javac [ javac -classpath ]. Complied. But when I tried to run it gave me an exception "Exception in thread "main" java.lang.NoClassDefFoundError". Does anyone know what's wrong ?
run the code after compile
compile javac TestTwo.java
run after compile java TestTwo
try this
javac -d path cname.java
so write the code like this
javac -d c:\main testone.java javac -d c:\main testtwo.java
c:\main should exist in your pc
then while executing
java -cp path pn.classname
so whichever class contains main (say test2)
java -cp c:\main package1.testtwo

Basic questions about Java CLASSPATH

Suppose I just created a package "example" and have two classes inside it, "Main" and "Helper".
With the simplest possible compilation (e.g., $javac Main.java Helper.java) I am already able to run it fine as long as I am in the directory containing the example package, by typing this in the command line:
$java example.Main
Questions:
Why would I want to set a CLASSPATH given I can already run the program? I am guessing to be able to type "$java example.Main" from any directory on my machine, but I am not sure.
What happens when I type "java -cp /path/to/your/java/class/file Main" on the command line? Right now I picture there's file containing all the different classpaths, and that command will just add another one to it. Is it the case?
Is there a difference between using "CLASSPATH=/path/to/your/java/class/file" and "java -cp /path/to/your/java/class/file Main" on the command line? How come the second one has the name of the class (i.e. Main) in the end?
Yea, pretty much. That of course assumes you have the path to java in your PATH variable
-cp or -classpath adds it's option (a string) in front of whatever is in your CLASSPATH
Yes, there is a difference. Using CLASSPATH is often more convenient as you tend to set your CLASSPATH once. From then on, java Main is enough to execute the main class. With java -cp /path/to/your/java/class/file Main you have to type the -cp /path/to/your/java/class/file every time.
That being said, both CLASSPATH and -cp or -classpath options usually contain entries pointing to directories containing java libraries used by your program, not the directory of your program itself.

Categories