Java 11 Developer Certification - Basics
September 18, 2020
What we are covering in this lesson
- Creating a simple, executable java program
- Main java tools
- Class and source code naming, public and non-public types
- main method signature
- Create a simple jar and an executable jar
- Passing command line (cli) arguments to the main method
Create a simple, executable java program
Make sure to be able to create one of the simplest java programs, that writes one line to the console
public class HelloJava {
public static void main(String[] args) {
System.out.println("This executes, yay");
}
}
Java tools you are required to know for the certification
javac - compile java source code into bytecode and class files
Some frequently used options:
-d followed by the target directory, where the class should be created in
-g generates debugging information
-verbose prints information about what is going on during the compilation process
Here is how we compile the HelloJava.java source to HelloJava.class into the ../target directory, while printing out debugging and compiler processing information:
C:\Users\darva\IdeaProjects\j11-exam\src>javac HelloJava.java -d ../target -g -verbose
[parsing started SimpleFileObject[C:\Users\darva\IdeaProjects\j11-exam\src\HelloJava.java]]
[parsing completed 13ms]
[loading /modules/jdk.compiler/module-info.class]
[loading /modules/jdk.crypto.cryptoki/module-info.class]
...
[loading /modules/jdk.management/module-info.class]
[loading /modules/jdk.jlink/module-info.class]
[loading /modules/jdk.net/module-info.class]
[loading /modules/jdk.zipfs/module-info.class]
[search path for source files: .]
[search path for class files: C:\Users\darva\jdks\jdk-11\lib\modules,.]
...
[loading /modules/java.base/java/lang/CharSequence.class]
[wrote ..\target\HelloJava.class]
[total 149ms]
java - run a java application
Some frequently used options:
-cp, -classpath, --classpath followed by a ; separated list defines the:
- paths or
- jars or
- zip files where the java classes can be found.
For example we have the class file HelloJava.class in directory C:\Users\darva\IdeaProjects\j11-exam\target, here is how you execute it providing the full, absolute classpath:
java -cp C:\Users\darva\IdeaProjects\j11-exam\target HelloJava
-verbose:[class|module|gc|jni] is enabling verbose output about e.g.: each loaded class or garbage collection
C:\>java -verbose -cp C:\Users\darva\IdeaProjects\j11-exam\target HelloJava
[0.006s][info][class,load] opened: C:\Users\darva\jdks\jdk-11\lib\modules
[0.014s][info][class,load] java.lang.Object source: jrt:/java.base
[0.015s][info][class,load] java.io.Serializable source: jrt:/java.base
....
[0.171s][info][class,load] java.nio.CharBuffer source: jrt:/java.base
[0.171s][info][class,load] java.nio.HeapCharBuffer source: jrt:/java.base
[0.172s][info][class,load] java.nio.charset.CoderResult source: jrt:/java.base
This executes, yay
[0.172s][info][class,load] jdk.internal.misc.TerminatingThreadLocal$1 source: jrt:/java.base
[0.172s][info][class,load] java.lang.Shutdown source: jrt:/java.base
[0.173s][info][class,load] java.lang.Shutdown$Lock source: jrt:/java.base
new in JDK 11: we can invoke java on a single file java source code and execute it, without first compiling with javac. Class files do not get created, all the code is interpreted by the jvm
C:\Users\darva\IdeaProjects\j11-exam\src>dir
Volume in drive C is Windows
Volume Serial Number is 0052-1F15
Directory of C:\Users\darva\IdeaProjects\j11-exam\src
2020. 09. 18. 20:32 <DIR> .
2020. 09. 18. 20:32 <DIR> ..
2020. 09. 18. 17:47 126 HelloJava.java
1 File(s) 126 bytes
2 Dir(s) 353 405 181 952 bytes free
C:\Users\darva\IdeaProjects\j11-exam\src>java HelloJava.java
This executes, yay
What’s interesting though is that you can’t execute the source file as shown above, if your classpath already includes a compiled class file:
C:\Users\darva\IdeaProjects\j11-exam\target>dir
Volume in drive C is Windows
Volume Serial Number is 0052-1F15
Directory of C:\Users\darva\IdeaProjects\j11-exam\target
2020. 09. 18. 19:36 <DIR> .
2020. 09. 18. 19:36 <DIR> ..
2020. 09. 18. 19:17 537 HelloJava.class
2020. 09. 18. 19:36 797 HelloJava.jar
2 File(s) 1 334 bytes
2 Dir(s) 353 406 881 792 bytes free
C:\Users\darva\IdeaProjects\j11-exam\target>java ../src/HelloJava.java
error: class found on application class path: HelloJava
jar - manipulate (create, change, extract from) a Java ARchive
If you are familiar with the Unix tar command, then jar will not be a big challenge.
Some frequently used options:
-c, --create create a java archive (jar)
-t, --list list contents of a java archive (jar)
-x, --extract extract from the java archive (jar)
-f, --file the name of the jar archive (to be created, listed, etc…)
-v, --verbose verbose output of the operation
-C DIR change to the specified directory and include the follwoing file
-m, --manifest includes the manifest file provided
Let’s build a jar from an already existing class file that sits in ../target, and create the jar also in the ../target directory, then list its content:
C:\Users\darva\IdeaProjects\j11-exam\src> jar -cvf ../target/HelloJava.jar -C ../target HelloJava.class
added manifest
adding: HelloJava.class(in = 537) (out= 339)(deflated 36%)
C:\Users\darva\IdeaProjects\j11-exam\src>jar tvf ../target/HelloJava.jar
0 Fri Sep 18 19:36:48 CEST 2020 META-INF/
62 Fri Sep 18 19:36:48 CEST 2020 META-INF/MANIFEST.MF
537 Fri Sep 18 19:17:02 CEST 2020 HelloJava.class
Did you see that the jar execution already created a manifest for us, even though we did not specify -m ? Let’s see what’s in it. We are going to extract the manifest and print its content to the terminal:
C:\Users\darva\IdeaProjects\j11-exam\src>jar xvf ../target/HelloJava.jar META-INF/MANIFEST.MF
inflated: META-INF/MANIFEST.MF
C:\Users\darva\IdeaProjects\j11-exam\src>type META-INF\MANIFEST.MF
Manifest-Version: 1.0
Created-By: 11 (Oracle Corporation)
javap - disassemble class file(s)
-c Disassemble the code
Let us print out the source of our **HelloJava.class**
C:\Users\darva\IdeaProjects\j11-exam\target>javap -c HelloJava.class
Compiled from "HelloJava.java"
class HelloJava {
HelloJava();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String This executes, yay
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
jdeps - class dependency analyzer and jdeprscan deprecated api jar scanner
These will be discussed later in the modules section. [TODO]
How to name your java source files and what access modifiers should you use
The rule:
- Java requires that in a given source file there is zero or one type (class, interface, enum) with a public access modifier.
- If there is a type with public access modifier, the source filename must match that type with the public modifier
We have already seen a working exampe of the one-line print class, here we have a public class, which means we need to name the .java file the same as the class TODO.
Look at it how it fails to execute:
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ cat HelloJava.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("This executes, yay");
}
}
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ javac HelloJava.java
HelloJava.java:1: error: class HelloWorld is public, should be declared in a file named HelloWorld.java
public class HelloWorld {
^
1 error
The other case is when we do not have a public type in the source code, so the class can be different than the filename. Note, that the generated class is called as our class defined in the source. E.g.:
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ cat HelloJava.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("This executes, yay");
}
}
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ javac HelloJava.java
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ echo $?
0
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ ls -l HelloWorld.class
-rw-rw-r-- 1 darvat darvat 431 Sep 20 11:50 HelloWorld.class
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ java HelloWorld
This executes, yay
What happens if we have 2 or more non-public classes in our source code? In such a case all the classes get created. Let’s check out what the java compiler does:
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ cat HelloJava.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("This executes, yay");
}
}
class HelloMoon {
public static void main(String[] args) {
System.out.println("This also executes, yay");
}
}
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ javac HelloJava.java
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ ls -l
total 12
-rw-rw-r-- 1 darvat darvat 248 Sep 20 11:54 HelloJava.java
-rw-rw-r-- 1 darvat darvat 435 Sep 20 11:56 HelloMoon.class
-rw-rw-r-- 1 darvat darvat 431 Sep 20 11:56 HelloWorld.class
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ java HelloMoon
This also executes, yay
main method signature
Rule of thumb: in order to have a class to be executable
- a main method must exist
- it must be public and static
- the parameter must be a string array String[]
- the return type is always void
The most known way of declaring the above is
public static void main(String[] args)
However, using varargs (variable arguments) syntax in the argument definition is also OK
public static void main(String... args)
We can also throw an unhandled exception
public static void main(String args[]) throws Exception
The public and static keywords can be in any order
static public void main(String... args)
Additional modifiers are allowed in any order
- final
- strictfp
- synchronized
static synchronized public final strictfp void main(String... args) throws Exception
The parameter name can be called anything, not only args
public static void main(String ...myArgsForAStringArray)
Create a simple jar and an executable jar
Let’s create a simple jar (call it PrintHello.jar) in our out directory by adding a class to it (already exists as ./out/HelloJava.class) and then execute the class from within the jar:
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ jar -cvf out/PrintHello.jar -C ./out HelloJava.class
added manifest
adding: HelloJava.class(in = 471) (out= 312)(deflated 33%)
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ java -cp ./out/PrintHello.jar HelloJava
Hello Java!
If we want to create an executable jar, we need to make sure that we also add a manifest file to the archive, which describes what out main executable class is. See below what the syntax is for defining the main class in the manifest (check the printf line).
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ printf "Main-Class: HelloJava\n" > manifest.txt
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ cat manifest.txt
Main-Class: HelloJava
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ jar -cfm ./out/PrintHello.jar manifest.txt -C ./out HelloJava.class
darvat@tamas-OMEN:~/IdeaProjects/HelloJava$ java -jar ./out/PrintHello.jar
Hello Java!
Passing command line (cli) arguments to the main method
In order to demonstarte the tricky parts of how we can pass command line arguments to the main method, we need to write a short test class.
public class ArgPrinter {
public static void main(String... arguments) {
var i = 1;
for (String argument: arguments) {
System.out.println("ARG #" + i++ + ": " + argument );
}
}
}
We provide the following cli arguments to the programs to test the behaviour of different cases:
darvat@tamas-OMEN:~/IdeaProjects/HelloJava/src$ java ArgPrinter.java alfa,beta,gamma "delta epsilon" 'zeta eta'
ARG #1: alfa,beta,gamma
ARG #2: delta epsilon
ARG #3: zeta eta
What did we learn (remember we are doing it on Linux, you’ll see it in a minute why it’s important)?
- arguments are separated by space, not by comma
- on Linux - arguments surrounded by double or single quotes are considedered as one argument, excluding the
"
and'
However on Windows it behaves differently
C:\Users\darva\IdeaProjects\j11-exam\src> java ArgPrinter.java alfa,beta,gamma "delta epsilon" 'zeta eta'
ARG #1: alfa,beta,gamma
ARG #2: delta epsilon
ARG #3: `zeta
ARG #4: eta`
-
on Windows:
- arguments surrounded by double quotes are considedered as one argument
- single quotes are considered part of the string argument
That’s it for this lesson, happy learning