Our Devoxx Java Puzzler

This year Expedia Group sponsored Devoxx UK and I joined the Expedia booth as one of the representatives from Hotels.com (part of Expedia Group). As part of our booth, we created a Java puzzler which had a £200 holiday voucher for the winner (drawn from the correct answers to the puzzler). Immediately below is the puzzler. After the puzzler I’ll discuss the answers given, so if you want to have a go at the puzzler, avoid reading past this first code section, that is until you want to see the proposed answers.

package expedia.puzzler;
/**
* This class, unaltered, when run on a normal unaltered
* JVM and with no change to bootclasspath and no agentlib
* produces the output "goodbye". It actually produces
* "goodbye" on any JVM from 1.0 to 10.
*
* ‘java [OPTS] expedia.puzzler.PrintGoodbye’
*
* The question is, how can that be?
*
* Obviously this code itself wouldn’t produce "goodbye",
* so what could make it do so without changing this class?
* (hint, there is no need to use JNI)
*/
public class PrintGoodbye {
  public static void main(String[] args) {
String s = new String("hello");
System.out.println(s);
}
}

We tried this out on some developers before the event, and they found it challenging. And from the conversations we had at Devoxx, developers there also found it challenging. While at the booth I grabbed Mark Reinhold, Chief Architect of the Java Platform (here with me using our photobooth at Devoxx with a nice fishing marina he selected as our background), and it took him a few minutes to get a valid (and indeed the simplest) solution — mainly because he was thinking of esoteric answers before he finally said “oh, it’s trivial!”

Mark Reinhold, Chief Architect of the Java Platform on the right, with Java Champion Jack Shirazi

The simple solution

The simplest answer we were expecting was to define your own class called System in the same package as the PrintGoodbye class, and include that in the classpath eg

package expedia.puzzler;
/**
* Define this in the same package as PrintGoodbye
*/
public class System {
  public static System out = new System();
  public void println(String s) {
java.lang.System.out.println("goodbye");
}
}

Yes, as simple as that. When I pointed this out to most developers, I could see them metaphorically facepalm themselves.


Other solutions

We had many suggestions of using very esoteric options like editing the compiled bytecode to replace the string “hello” with “goodbye” or redefine the Unicode charset to have “hello” come out as “goodbye” and point the JVM at those. I don’t know if these would work, but no one provided a workable set of instructions to try them out so there weren’t any of those entries for me to test.

We also had people suggesting defining a String class in the same package as the PrintGoodbye class, and this seems like it should work similarly to the System class definition above. But it doesn’t. Because the Java language specification requires the JVM entrypoint to be a quite specific signature:

public static void main(java.lang.String[])

and if you create your own String class in the expedia.puzzler package, the PrintGoodbye class uses that String class instead in the main() method including for the parameter. That changes the main() signature and consequently that main() is no longer recognized by the JVM as a valid entrypoint for the program. It does compile, but if you try to run that solution you would get an error “Error: Main method not found …”. So it’s an incorrect answer.

We also had several solutions redefining the line.separator -Dline.separator=”\b\b\b\b\b\bgoodbye\n”. I thought that was quite clever. But sadly it didn’t work. I ran it and the output was “hello\b\b\b\b\b\bgoodbye\n”. It might have worked on some system command lines, but I tried all solutions in a Linux shell and a Windows command prompt, and it didn’t work on either for me.

Finally we had technically correct solutions that you might not consider useful, but they did work when I tested them so we considered them correct and entered them in the prize draw. These were three types:

  1. Create your own launcher class as the main class and put that in the [OPTS] (we forgot to rule that out in the instructions so we decided we couldn’t say it was wrong). The class needs to take the PrintGoodbye class as an argument, then first print “goodbye” and then call PrintGoodbye while redirecting the output from PrintGoodbye (it’s wrong if you don’t redirect the output, since then the output is “goodbye\nhello”). Just ignoring the PrintGoodbye argument would be wrong since the instructions specifically require the class to run.
  2. Load your own classloader using the java.system.class.loader property which redefines the main of PrintGoodbye to print “goodbye” (dubious since the class is altered, but I decided it was valid. And quite inventive)
  3. And finally a very cheeky
java expedia.puzzler.PrintGoodbye | echo "goodbye"

which did actually work on both my test shells (the “hello” is just dumped by the echo command; both the pipe and the echo command work on both Windows and Unix. A similar solution using a redirect instead of pipe didn’t work because /dev/null doesn’t work on Windows).


It was fun creating the puzzler, fun discussing it with the developers at Devoxx and fun looking at the solutions suggested. All in all, a fun experience.