Java 11 Developer Certification - Basics

September 18, 2020

What we are covering in this lesson

  1. Creating a simple, executable java program
  2. Main java tools
  3. Class and source code naming, public and non-public types
  4. main method signature
  5. Create a simple jar and an executable jar
  6. 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 emoji-+1

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:

  1. Java requires that in a given source file there is zero or one type (class, interface, enum) with a public access modifier.
  2. 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 emoji-muscle emoji-thumbsup