Bad String
This program has two threads printing messages alternatively. However if you change a String
from "cC"
to "cc"
it doesn’t print anything, WHY?
public class PingPongMain {
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
synchronized ("bb") {
while (true) {
"bb".wait();
"bb".notifyAll();
System.out.println("b");
}
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}).start();
Thread.sleep(100);
setString("bb", 'c', 'C');
new Thread(() -> {
try {
// change "cC" to "cc" and this program prints nothing.
synchronized ("cC") {
while (true) {
"cC".notifyAll();
"cC".wait();
System.out.println("c");
}
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}).start();
}
public static void setString(String s, char... chars) {
try {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(s, chars);
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
The solution is below
.
.
.
![omg wtf](https://vanilla-java.github.io/images/omg_wtf.jpg)
.
.
.
A combination of strangeness
There is a couple of elements to this puzzle
-
using a String literal as a Object to lock on.
-
corrupting a String in the literal pool.
-
replacing one String with another with the same hashCode so the replacement is found. "bb".hashCode() == "cC".hashCode()