|
The Java Specialists' Newsletter
Issue 199 2012-02-23
Category:
Language
Java version: Java 1 - Java 7 Hacking Java Surreptitiouslyby Dr. Heinz M. KabutzAbstract: 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.
Sign up for our new Concurrency Specialist Course
here!
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 void done() {
if (clowns.size() == 20) {
// The goal is to reach this line
System.out.println("I'm a Volkswagen with 20 clowns!");
}
}
}
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.
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.
Kind regards
Heinz
Language Articles
Related Java Course
Discuss at The Java Specialist Club
|