Hello, World and friends.

exercise No. 1

Extending class HelloWorld

Q:

  1. Create a class HelloWorld by using your favourite text editor ( nano, vim, atom ...) inserting the following code into a file HelloWorld.java:

    public class HelloWorld {
    
       public static void main(String[] args) {
    
          System.out.println("Hello, World ...");
    
       }
    }
  2. Compile HelloWorld.java:

    javac HelloWorld.java

    This should result in a newly generated bytecode file HelloWorld.class:

    ls 
    HelloWorld.class
    HelloWorld.java
  3. Execute HelloWorld.class by:

    java HelloWorld

    Warning

    Executing java HelloWorld.class will not work.

    You should see the following output in your terminal:

    Hello, World ...

    Extend the above code to produce a whole paragraph of sentences rather than just one single line. Your output might read:

    Those who can do.
    Those, who cannot, teach.
    Those, who cannot teach, lecture trainee teachers teaching methodology.

A:

After creating a file HelloWorld.java we execute the compilation step:

>javac HelloWorld.java 
>
>ls -l 

-rw-r--r-- 1 goik fb1prof 426 Sep 25 09:14 HelloWorld.class 
-rw-r--r-- 1 goik fb1prof 124 Sep 23 17:44 HelloWorld.java 

The javac command will read HelloWorld.java. If no errors are found a HelloWorld.class bytecode file is being generated.

The ls command lists all files and directories being found in your current working directory. The -l option will create a longer listing providing privilege, user and group ownership, file size and modification time meta data.

The bytecode file HelloWorld.class results from compilation in .

The source file containing our class definition code. Note Sep 25 09:14 being more recent than Sep 23 17:44. This reflects the fact that compilation happened after editing HelloWorld.java.

Execution requires a Java runtime by virtue of the java command:

Starting the Java runtime. HelloWorld is a command line parameter to java.

The source line System.out.println("Hello, world") causes the Java runtime writing the string "Hello, world" to the operating system's standard output channel appending a newline character.

>java HelloWorld 
Hello, world 

There are several options for creating a whole paragraph spanning multiple text lines:

  1. Using Java 13 multiline string literals (easy):

    public static void main( String[] args ) {
      System.out.println("""
        Those who can do.
        Those, who cannot, teach.
        Those, who cannot teach, lecture trainee teachers teaching methodology.""" );
    }
  2. Straightforward: Using multiple print statements:

    public class HelloWorld {
    
     public static void main(String[] args) {
        System.out.println("Those who can do.");
        System.out.println("Those, who cannot, teach.");
        System.out.println(
          "Those who cannot teach lecture trainee teachers teaching methodology.");
       }
    }
  3. Long strings exceeding your editor's desired maximum line length may be decomposed into smaller chunks using the + ❶ string concatenation operator:

    public static void main(String[] args) {
      System.out.println("Those who can do.");
      System.out.println("Those, who cannot, teach.");
      System.out.println("Those, who cannot teach, " + ❶
         "lecture trainee teachers teaching methodology."); // continuation line
    }
  4. The System.out.println(...) method adds a final line break to your output. The ASCII newline character \n ❶ allows for using just a single System.out.println("...") statement:

    public static void main(String[] args) {
      System.out.println(
        "Those who can do.\n" ❶ +
        "Those, who cannot, teach.\n" ❶ +
        "Those, who cannot teach, " +
        "lecture trainee teachers teaching methodology."); // No \n at end, println does it.
    }

exercise No. 2

Renaming a class file

Q:

Consider HelloWorld.java again:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world");
    }
}
  1. Rename your existing HelloWorld.java file to Advance.java and try to compile it. What happens and why does it happen?

  2. How do you solve the problem by editing the file's content?

A:

  1. Renaming a Java class file without renaming a contained public class name results in a compile time error:

    >mv HelloWorld.java Advance.java 
    >
    >javac Advance.java 
    Advance.java:2: error: class HelloWorld is public, should be declared in a file named HelloWorld.java
    public class HelloWorld {
           ^ 
    1 error 

    We rename HelloWorld.java to Advance.java on file system level without touching its content.

    Trying to compile Advance.java.

    Failure: The file Advance.java still contains a public class HelloWorld definition. But Java requires the class name being equal to the containing file's base name appending a .java extension.

    This error belongs to the wide class of compile time errors. More specific it is being called a syntax error violating Java language constraints.

  2. Compilation requires replacing the class name HelloWorld by Advance:

    public class Advance {
      public static void main(String[] args) {
        System.out.println("Hello, world");
      }
    }
    >javac Advance.java 
    >
    >java Advance
    Hello, world

exercise No. 3

Editing and compilation

Q:

Consider the following class definition in a HelloWord file:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("I have changed!");
    }
}

On execution a newbie programmer is stunned still seeing the former "Hello, world" string:

>java HelloWorld
Hello, world

The file system view reads:

>ls -l
-rw-r--r-- 1 goik fb1prof 426 Sep 25 10:45 HelloWorld.class
-rw-r--r-- 1 goik fb1prof 126 Sep 25 10:48 HelloWorld.java

Whats wrong here? Why does the "I have changed!" string does not show up?

A:

The file system reveals HelloWorld.class being about three minutes older than HelloWorld.java:

>ls -l
-rw-r--r-- 1 goik fb1prof 426 Sep 25 10:45 HelloWorld.class
-rw-r--r-- 1 goik fb1prof 126 Sep 25 10:48 HelloWorld.java

The programmer likely edited HelloWorld.java and forgot to invoke the compiler by executing javac HelloWorld.java. As a consequence the now outdated HelloWorld.class bytecode file was not replaced by a current version thus not reflecting the change of HelloWorld.java and thus became outdated.

This is a common beginner's error: Integrated development environments like Intellij IDEA and build tools like Maven relieve you from the manually keeping track of dependencies burden: Editing a source code file will trigger compilation automatically. We'll turn to those higher level tools after finishing our basic tour on pure Java javac / java commands and plain text source code editing.

exercise No. 4

Editing bytecode

Q:

We reconsider the bytecode example from Figure 34, “Java byte code file HelloWorld.class being generated from a HelloWorld.java class file:

Êþº¾^@^@^@6^@^]
^@^F^@^O        ^@^P^@^Q^H^@^R
^@^S^@^T^G^@^U^G^@^V^A^@^F<init>^A^@^C()V^A^@^DCode^A^@^OLineNumberTable^A^@^Dmain^A^@^V(\
  [Ljava/lang/String;)V^A^@
SourceFile^A^@^OHelloWorld.java^L^@^G^@^H^G^@^W^L^@^X^@^Y^A^@^LHello, world^G^@^Z^L^@^[^@\
  ...
  1. Use your favourite text editor for overwriting the string "Hello, world" by "Software joy" in HelloWorld.class (Not in HelloWorld.java!).

    Êþº¾^@^@^@6^@^]
    ^@^F^@^O        ^@^P^@^Q^H^@^R
    ^@^S^@^T^G^@^U^G^@^V^A^@^F<init>^A^@^C()V^A^@^DCode^A^@^OLineNumberTable^A^@^Dmain^A^@^V(\
      [Ljava/lang/String;)V^A^@
    SourceFile^A^@^OHelloWorld.java^L^@^G^@^H^G^@^W^L^@^X^@^Y^A^@^LSoftware joy^G^@^Z^L^@^[^@\
      ...

    Try to execute this bytecode file (without recompiling). What do you observe?

  2. Recompile and repeat the process starting from a sound HelloWorld.class file. This time use a binary editor like hexedit or ghex instead.

    Tip

    Read your editor's documentation. Using hexedit HelloWorld.class in a terminal just requires:

    • The tab key switching to the ASCII section in the right pane.

    • Ctrl-X for leaving the editor and hitting the Y key to persist your changes.

  3. Start again from a freshly compiled HelloWorld.class. Use a binary editor again to append an exclamation mark as in "Hello, world!". The string's length will thus be increased by 1. What happens on execution?

A:

  1. Using a simple text editor doesn't work:

    >java HelloWorld
    Error: LinkageError occurred while loading main class HelloWorld
    	java.lang.ClassFormatError: Extra bytes at the end of class file HelloWorld
    

    This error actually depends on your text editor choice: When using vim or nano analyzing the modified bytecode file's content reveals the culprit at the very end:

    ...
    00000090   17 0C 00 18  00 19 01 00  0C 43 65 6C  6C 6F 2C 20  .........Hello,
    000000A0   77 6F 72 6C  64 07 00 1A  0C 00 1B 00  1C 01 00 0A  world...........
    ...
    00000190   00 0A 00 00  00 0A 00 02  00 00 00 03  00 08 00 04  ................
    000001A0   00 01 00 0D  00 00 00 02  00 0E 0A               ...........

    The 0A (10 in hexadecimal notation) is being appended to the bytecode file both by vim and nano. This is the ASCII value corresponding to a linefeed character. Both editors thus add an empty new line on saving thereby corrupting the bytecode file.

    The emacs editor for example refrains from auto-adding newlines and doesn't cause this problem.

  2. In any case using a binary editor like hexedit or ghex leads to success :

      ...      ...
    00000070   ...  61 0C 00 07  rceFile...HelloWorld.java...
    0000008C   ...  79 07 00 1A  .............Software joy...
    000000A8   ...  61 2F 6C 61  ........HelloWorld...java/la
      ...      ...

    Executing java HelloWorld:

    >java HelloWorld
    Software joy
  3. Extending the string even by just one character corrupts the bytecode file:

    >java HelloWorld
    Error: LinkageError occurred while loading main class HelloWorld
    	java.lang.ClassFormatError: Unknown constant tag 33 in class file HelloWorld

    Using hexedit we find the following content within the unspoiled bytecode file:

    00 08 07 00  17 0C 00 18  00 19 01 00  0C 48 65 6C  6C 6F 2C 20  77 6F 72 6C  64 07 00 1A
                                                                                     
                        ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛                        
                                                                          will be overridden by
    .............Hello, world...                                            »!« or 21 respectively

    Thus appending an exclamation mark will override the hexadecimal 07 value immediately following the "Hello, world" string with a new value of 21 (ASCII for !). Apparently this value serves some purpose with respect to the virtual machine and must therefore not be altered. This is the byte code verifier's responsibility as being outlined in Figure 36, “Executing byte code file HelloWorld.class.

Overall conclusion: Tinkering with bytecode files is a bad idea unless you have a good reason and know what you are doing.