Running on Java 24-ea+24-2960 (Preview)
Home of The JavaSpecialists' Newsletter

199Hacking Java Surreptitiously

Author: Dr. Heinz M. KabutzDate: 2012-02-23Java Version: 5Category: Language
 

Abstract: Surreptitious: stealthy, furtive, well hidden, covert. In this newsletter we will show two Java puzzles written by Wouter Coekaerts that require a surreptitious solution. You cannot do anything to upset the security manager.

 

Welcome to the 199th issue of The Java(tm) Specialists' Newsletter sent to you from the Island of Crete. Greece is an interesting place to live at the moment. For some reason, the weather is still exactly the same as every year at this time. Somehow the rain clouds seem to not have heard that we have a financial crisis here. Or maybe they do not care? And the warm sun that breaks through occasionally also seem oblivious to our pain. Not even the birds singing their morning greetings have changed their melody to a dirge. Life goes on.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

Hacking Java Surreptitiously

Java puzzles and brain-teasers are a fun way to test your skills as a Java programmer. It does not matter whether you are preparing for the Java Programmer's Certification Exam or for a job interview or if you just enjoy the challenge.

Wouter Coekaerts sent me some puzzles last year that were incredibly clever and funny at the same time. We need to hack Java surreptitiously, meaning that we must generate surprising results without resorting to anything that would upset the security manager. After pleading with him for months, he finally agreed to publish his puzzles.

In his first puzzle we need to squeeze 20 clowns into a Volkswagen that has a maximum capacity of 5. We start with the Clown and Volkswagen classes:

package clowns;

public class Clown {
}

package clowns;

import java.util.*;

public class Volkswagen {
  private static final int CAPACITY = 5;
  private HashSet<Clown> clowns = new HashSet<Clown>();

  public synchronized void add(Clown clown) {
    if (clowns.size() >= CAPACITY) {
      throw new IllegalStateException("I'm full");
    } else {
      clowns.add(clown);
    }
  }

  public synchronized boolean done() {
    if (clowns.size() == 20) {
      // The goal is to reach this line
      System.out.println("I'm a Volkswagen with 20 clowns!");
      return true;
    }
    return false;
  }
}

We are not allowed to change either of the Clown nor the Volkswagen classes. We also cannot use anything that would change those classes at runtime, so AspectJ is forbidden. It needs to be solved with plain Java. The hack has to be done surreptitiously, without arousing any suspicion. Thus you have to always be able to run your code with the "-Djava.security.manager" flag enabled. If you are in any doubt, please read the exact rules.

Here is the you.You class, which you need to modify in such a way that the code above prints "I'm a Volkswagen with 20 clowns!":

package you;

import clowns.*;

public class You {
  public static void main(String args[]) {
    // TODO put 20 clowns into a Volkswagen
    Volkswagen vw = new Volkswagen();
    for (int i = 0; i < 20; i++) {
      vw.add(new Clown());
    }
    vw.done();
  }
}

After you have solved it, you can head over to Wouter's blog to check whether your solution is correct. According to his Google Analytics, only 0.5% of visitors managed to solve this one. I found two solutions, but only after thinking about this for a very long time. His puzzles are not easy. If you have just started coding Java, this is not for you. You can also look at my solution in the class YouSolution.

Dreaming Recursively

In his second puzzle, published today, we want to dream recursively. A dream within a dream within a dream. The dream is real.

You can see that level++ and level-- calls are paired. The level-- call happens in the finally block, thus it always has to happen after the dream is done.

package sleep;

import dream.*;

public class Sleeper {
  private int level;

  public synchronized int enter(Dream dream) {
    level++;
    try {
      dream.dream(this);
    } finally {
      level--;
    }
    return level;
  }
}

The Main class constructs a Sleeper and makes him enter his dream. Your goal is to make the main method print out "Am I still dreaming?".

package sleep;

import dream.*;

public class Main {
  public static void main(String[] args) {
    if (new Sleeper().enter(new Dream()) != 0) {
      // The goal is to reach this line
      System.out.println("Am I still dreaming?");
    }
  }
}

Here is the file that you need to edit:

// this is the only file you're allowed to edit
package dream;

import sleep.*;

public class Dream {
  public void dream(Sleeper s) {
    // TODO implement me
  }
}

The puzzle is possible to solve. It took me about 15 minutes. Once you have solved it, you can post your solution in the comments section of Wouter's blog. He will keep it hidden for about a week and then post the solution, together with your comment. The first correct solution will be mentioned in his next puzzle. You can also have a look at my solution in the class DreamSolution.

Kind regards

Heinz

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Superpack '23

Superpack '23 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...