Running a JMH test like this:
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class Synchronization {
@Benchmark
public Object blackhole() {
Object o = new Object();
synchronized (o) {}
return o;
}
}
...with JMH that enables compiler blackholes, shows that the synchronization for the object is eliminated by EA, because the object is deemed non-escaping. Blackholes do prevent scalar replacement, but not other optimizations made available by EA.
While this is not exactly a bug in compiler blackhole implementation, this diverts from the status quo of plain Java JMH blackholes: they were fully opaque for EA, that is the arguments were globally escaping. We should probably match that behavior to avoid surprises for users. See the real world sighting of the related EA-enabled optimization -- eliding constructor storestore barriers -- here: https://mail.openjdk.java.net/pipermail/jmh-dev/2022-April/003428.html
One can still get current compiler blackhole behavior by doing the non-inlined empty method like:
@Benchmark
public void dontinline() {
Object o = new Object();
synchronized (o) {}
sink(o);
}
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public void sink(Object o) {}