I wanted to check out some new features of java 11 which was released two days ago.
JEP 330 states that I could launch a Java-Source-Code-Program without compiling.
It should also support the usage of Shebang-Files.
Hence I have written this small Hello-World Program Test.java:
#!/opt/java/jdk-11/bin/java --source 11
public class Test
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
I downloaded JDK 11 and extracted it to /opt/java.
Hence the Shebang itself is working.
I.e. executing /opt/java/jdk-11/bin/java --version gives me
openjdk 11 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
After making Test.java executable (using chmod +x Test.java) the execution is failing.
I.e. ./Test.java gives me:
./Test.java:1: error: illegal character: '#'
#!/opt/java/jdk-11/bin/java --source 11
^
./Test.java:1: error: class, interface, or enum expected
#!/opt/java/jdk-11/bin/java --source 11
^
2 errors
error: compilation failed
As soon as I remove the Shebang-Line from Test.java and start it with /opt/java/jdk-11/bin/java --source 11 Test.java
everything is working like a charm and I get the expected output: Hello World!
My machine is running Ubuntu 17.04.
I have linked javac to the one from JDK 11 (i.e. executing javac -version gives javac 11).
The file name must not end with .java in order for the java executable to ignore the shebang line. You can use a different extension, or just have no extension at all (which is what they do in the JEP example and is what I would recommend).
From JEP 330 (emphasis added):
When the launcher reads the source file, if the file is not a Java source file (i.e. it is not a file whose name ends with .java) and if the first line begins with #!, then the contents of that line up to but not including the first newline are ignored when determining the source code to be passed to the compiler. The content of the file that appears after the first line must consist of a valid CompilationUnit as defined by §7.3 in the edition of the Java Language Specification that is appropriate to the version of the platform given in the --source option, if present, or the version of the platform being used to run the program if the --source option is not present.
It doesn't need to end with ".sh" specifically; also, that's potentially misleading because the file is not actually a shell script.
A bit of trial and error gave me the correct solution.
It was the file extension .java which causes those problems.
I.e. if I rename the file to Test.sh everything is working.
Here is a complete Hello-World-Shebang-Example:
Create a File Test.sh with content like
#!/opt/java/jdk-11/bin/java --source 11
public class Test
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
Make it executable (i.e. chmod +x Test.sh).
Last but not least execute it using ./Test.sh
According to the JEP you've linked to (see the shebang files section), the shebang file is to be used to launch the java process, not to be used as a parameter for java:
A shebang file to invoke the Java launcher using source-file mode must begin with something like:
#!/path/to/java --source version
For example, we could take the source code for a "Hello World" program, and put it in a file called hello, after an initial line of #!/path/to/java --source 10, and then mark the file as executable. Then, if the file is in the current directory, we could execute it with:
$ ./hello
In other words, what you want to do is rather make Test.java executable. You'd also have to rename it since it won't work as shebang and strip first line when it's named *.java.
$ move Test.java test
$ chmod +x test
$ ./test
This will launch shebang processor which will strip first line and pass the rest of the script to /path/to/java and Java will compile the script and run the main method.
Related
If I remember correctly
javac filename.java -> compile and generates classname.class(es)
java classname without .class extension
But when I try java filename.java executes successfully while java classname command gives the following error ,
Error: Could not find or load main class HelloWorld
Caused by: java.lang.ClassNotFoundException: HelloWorld
java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
// Prints "Hello, World" in the terminal window.
System.out.println("Hello, World");
}
}
javap HelloWorld.class is giving below output
Compiled from "HelloWorld.java"
public class HelloWorld {
public HelloWorld();
public static void main(java.lang.String[]);
}
java HelloWorld.java -> executes fine, no class file generated.
java HelloWorld -> didn't execute.
Any idea why the program is behaving like this?
After some help from some stackoverflow veterans in the comment section I was able to understand what went wrong.
The latest version of Java have introduced launching single file source code directly using Java command.
from oracle docs.
To launch a single source-file program:
java [options] source-file [args ...]
To run Helloworld.java, you can directly call execute java Helloworld.java it will execute the java program and gives output without generating .class file in the current directory.
Why old way of running java class file didn't work for me?
I had a class path variable 'CLASSPATH' in my environment, so when I execute java HelloWorld it is not looking for class in current directory. Give java -cp . to explicitly give current directory to classpath.
java -cp . HelloWorld
Credits: Jon Skeet,Joachim Sauer, rzwitserloot
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)
I have a set of instructions to create a Java application that takes multiple arguments when running the application from a CMD line.
The instructions state:
Thus, using the example set of above, assuming the main() method of your program is in a class called JavaClassName, the output should be:
$ java JavaClassName 4 7 file.csv
program output here
My question is:
Isn't this skipping the compile process?
Would they assume that loading the Java classes onto a computer that has never run this application before (or a directory with purely the .java files needed to run); running the cmd
$ java JavaClassName 4 7 file.csv
would output something?
Sidenote: Currently, running that CMD outputs
Error: Could not find or load main class JavaClassName
Have ran through multiple SO questions and online tutorials trying to get this to even run but I have yet to get it to work.
You ask:
Isn't this skipping the compile process?
Absolutely yes. A command line like java JavaClassName 4 7 file.csv assumes that there is a compiled class file "JavaClassName.class" in the current directory (or in some other directory or Zip/Jar file found in the CLASSPATH environment variable). And yes, to produce that "JavaClassName.class" class file, you have to use a java compiler first.
from Java 10 it is possible to run java programs that fit a single file without manually run the compiler first.
It will be compiled on the fly before execution. Nice and useful for scripting.
e.g. writing HelloWorld.java file
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World");
}
}
we can run it as
java HelloWorld.java
We can also add more classes in the single file.
from Java 11 we can also use shebang files
we have to specify which version of the java language you want to use
we have to save the file without .java extension
remember to give executable permissions chmod +x HelloWorld
writing HelloWorld file
#!/path/to/java --source 11
public class HelloWorld{
public static void main(String[] args) {
System.out.println("Hello World");
}
}
and we can run it as
./HelloWorld
I'm trying to execute a Java program from the command line in Windows. Here is my code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyFile
{
public static void main(String[] args)
{
InputStream inStream = null;
OutputStream outStream = null;
try
{
File afile = new File("input.txt");
File bfile = new File("inputCopy.txt");
inStream = new FileInputStream(afile);
outStream = new FileOutputStream(bfile);
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0)
{
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
System.out.println("File is copied successful!");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
I'm not sure how to execute the program - any help? Is this possible on Windows? Why is it different than another environment (I thought JVM was write once, run anywhere)?
Source: javaindos.
Let's say your file is in C:\mywork\
Run Command Prompt
C:\> cd \mywork
This makes C:\mywork the current directory.
C:\mywork> dir
This displays the directory contents. You should see
filenamehere.java among the files.
C:\mywork> set path=%path%;C:\Program Files\Java\jdk1.5.0_09\bin
This tells the system where to find JDK programs.
C:\mywork> javac filenamehere.java
This runs javac.exe, the compiler. You should see nothing but the
next system prompt...
C:\mywork> dir
javac has created the filenamehere.class file. You should see
filenamehere.java and filenamehere.class among the files.
C:\mywork> java filenamehere
This runs the Java interpreter. You should then see your program
output.
If the system cannot find javac, check the set path command. If javac
runs but you get errors, check your Java text. If the program
compiles but you get an exception, check the spelling and
capitalization in the file name and the class name and the java
HelloWorld command. Java is case-sensitive!
To complete the answer :
The Java File
TheJavaFile.java
Compile the Java File to a *.class file
javac TheJavaFile.java
This will create a TheJavaFile.class file
Execution of the Java File
java TheJavaFile
Creation of an executable *.jar file
You've got two options here -
With an external manifest file :
Create the manifest file say - MANIFEST.mf
The MANIFEST file is nothing but an explicit entry of the Main Class
jar -cvfm TheJavaFile.jar MANIFEST.mf TheJavaFile.class
Executable by Entry Point:
jar -cvfe TheJavaFile.jar <MainClass> TheJavaFile.class
To run the Jar File
java -jar TheJavaFile.jar
Complile a Java file to generate a class:
javac filename.java
Execute the generated class:
java filename
In case your Java class is in some package. Suppose your Java class named ABC.java is present in com.hello.programs, then you need to run it with the package name.
Compile it in the usual way:
C:\SimpleJavaProject\src\com\hello\programs > javac ABC.java
But to run it, you need to give the package name and then your java class name:
C:\SimpleJavaProject\src > java com.hello.programs.ABC
Since Java 11, java command line tool has been able to run a single-file source-code directly. e.g.
java HelloWorld.java
This was an enhancement with JEP 330: https://openjdk.java.net/jeps/330
For the details of the usage and the limitations, see the manual of your Java implementation such as one provided by Oracle: https://docs.oracle.com/en/java/javase/11/tools/java.html
Assuming the file is called "CopyFile.java", do the following:
javac CopyFile.java
java -cp . CopyFile
The first line compiles the source code into executable byte code. The second line executes it, first adding the current directory to the class path (just in case).
It is easy. If you have saved your file as A.text first thing you should do is save it as A.java. Now it is a Java file.
Now you need to open cmd and set path to you A.java file before compile it. you can refer this for that.
Then you can compile your file using command
javac A.java
Then run it using
java A
So that is how you compile and run a java program in cmd.
You can also go through these material that is Java in depth lessons. Lot of things you need to understand in Java is covered there for beginners.
You can compile any java source using javac in command line ; eg, javac CopyFile.java.
To run : java CopyFile.
You can also compile all java files using javac *.java as long as they're in the same directory
If you're having an issue resulting with "could not find or load main class" you may not have
jre in your path. Have a look at this question:
Could not find or load main class
On Windows 7 I had to do the following:
quick way
Install JDK http://www.oracle.com/technetwork/java/javase/downloads
in windows, browse into "C:\Program Files\Java\jdk1.8.0_91\bin" (or wherever the latest version of JDK is installed), hold down shift and right click on a blank area within the window and do "open command window here" and this will give you a command line and access to all the BIN tools. "javac" is not by default in the windows system PATH environment variable.
Follow comments above about how to compile the file ("javac MyFile.java" then "java MyFile") https://stackoverflow.com/a/33149828/194872
long way
Install JDK http://www.oracle.com/technetwork/java/javase/downloads/index.html
After installing, in edits the Windows PATH environment variable and adds the following to the path C:\ProgramData\Oracle\Java\javapath. Within this folder are symbolic links to a handful of java executables but "javac" is NOT one of them so when trying to run "javac" from Windows command line it throws an error.
I edited the path: Control Panel -> System -> Advanced tab -> "Environment Variables..." button -> scroll down to "Path", highlight and edit -> replaced the "C:\ProgramData\Oracle\Java\javapath" with a direct path to the java BIN folder "C:\Program Files\Java\jdk1.8.0_91\bin".
This likely breaks when you upgrade your JDK installation but you have access to all the command line tools now.
Follow comments above about how to compile the file ("javac MyFile.java" then "java MyFile") https://stackoverflow.com/a/33149828/194872
STEP 1: FIRST OPEN THE COMMAND PROMPT WHERE YOUR FILE IS LOCATED. (right click while pressing shift)
STEP 2: THEN USE THE FOLLOWING COMMANDS TO EXECUTE.
(lets say the file and class name to be executed is named as Student.java)The example program is in the picture background.
javac Student.java
java Student
As of Java 9, the JDK includes jshell, a Java REPL.
Assuming the JDK 9+ bin directory is correctly added to your path, you will be able to simply:
Run jshell File.java — File.java being your file of course.
A prompt will open, allowing you to call the main method: jshell> File.main(null).
To close the prompt and end the JVM session, use /exit
Full documentation for JShell can be found here.
Now (with JDK 9 onwards), you can just use java to get that executed.
In order to execute "Hello.java" containing the main, one can use:
java Hello.java
You do not need to compile using separately using javac anymore.
You can actually run Java program as you would shell or python scripts without manually compile the Java file, as described in
JEP 330. That is available since JDK 11.
If you create a file testing, and put the following you should be able to run it as command testing. You need to make it executable in Linux and Mac OSX with chmod +x testing.
#!/usr/bin/env java --source 11
public class Test {
public static void main(String [] args) {
System.out.println("Hello world!");
System.exit(0);
}
}
You are not allowed to use the file extension .java in the previous example.
$ chmod +x testing
$ ./testing
Hello world!
$
But you can still execute if it is was name Test.java without the shebang "#!" prefix like this:
public class Test {
public static void main(String [] args) {
System.out.println("Hello again!");
System.exit(0);
}
}
Then execute the file Test.java with following command:
$ java Test.java
Hello again!
$
So this works as long as you have a new enough Java compiler in the path, check with java -version. More information in this blog.
I'm trying to compile my programs using the command prompt on Windows 7. I'm having a problem when I during compile. I created a test program:
class test
{
public static void main (String args[])
{
System.out.println("this is working!!!!!!");
}
}
I use the following instructions from the command line:
cd \
cd summer
Javac test.java
java test
I have even tried using javaw and I get the same message but in a pop-up box
Could not find the main class, program will exit.
Any suggestions?
It seems your JDK and JVM have different editions.
You are using different versions of JDK. Check the versions on your javac vs java. This error is telling you that your java and compiled class are not same versions. Check your path for configuration, type "set" in dos to see details.
Example: If you compiled your class with javac (version 7) and execute it with java (version 6)