On Tue, 12 Jul 2022 09:18:19 GMT, Raffaello Giulietti <d...@openjdk.org> wrote:
>> `BigInteger.powerCache` is volatile and should be assigned only once in >> static initializer. > > Usually yes, but since a static initializer is executed by at most one thread > by using a locking protocol before any other static code is ever executed, > the runtime _could_ (but I'm not sure it it really does) treat the volatile > in the for loop as a local. > But I would approve your change because it makes this more explicit. @rgiulietti I've copy-pasted class-loading benchmark from JMH samples @State(Scope.Thread) @Warmup(iterations = 10, time = 1) @Measurement(iterations = 10, time = 5) @Fork(value = 5, jvmArgsAppend = {"-Xms1g", "-Xmx1g"}) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class Classy { @Benchmark public Class<?> load() throws ClassNotFoundException { return Class.forName("com.tsypanov.slp.Sample", true, new XLoader()); } public static class XLoader extends URLClassLoader { private static final byte[] X_BYTECODE = new byte[]{ /*..*/}; public XLoader() { super(new URL[0], ClassLoader.getSystemClassLoader()); } @Override protected Class<?> findClass(final String name) { return defineClass(name, X_BYTECODE, 0, X_BYTECODE.length); } } } and used it to measure loading a class from `byte[]` copied from the following class compiled: class Sample { static volatile int[] items = new int[100]; static { for (int i = 0; i < items.length; i++) { items[i] = ThreadLocalRandom.current().nextInt(); } } } I ran the benchmark with `java -jar target/sleep-benchmarks.jar Classy -prof cl` and for the version above got these results (Java 17): Benchmark Mode Cnt Score Error Units Classy.load avgt 50 96247.202 ± 548.137 ns/op Classy.load:·class.load avgt 50 259912.089 ± 1485.314 classes/sec Classy.load:·class.load.norm avgt 50 1.000 ± 0.001 classes/op Classy.load:·class.unload avgt 50 260243.318 ± 3673.515 classes/sec Classy.load:·class.unload.norm avgt 50 1.001 ± 0.014 classes/op Then I've modified the class in the same way I did in this PR: class Sample { static volatile int[] items; static { int[] items = new int[100]; for (int i = 0; i < items.length; i++) { items[i] = ThreadLocalRandom.current().nextInt(); } Sample.items = items; } } and for modified code got Benchmark Mode Cnt Score Error Units Classy.load avgt 50 63955.673 ± 147.470 ns/op Classy.load:·class.load avgt 50 391101.854 ± 925.013 classes/sec Classy.load:·class.load.norm avgt 50 1.000 ± 0.001 classes/op Classy.load:·class.unload avgt 50 390800.851 ± 2307.589 classes/sec Classy.load:·class.unload.norm avgt 50 0.999 ± 0.006 classes/op >From this I conclude that volatile costs are still there no matter whether we >deal with static or non-static initializers. ------------- PR: https://git.openjdk.org/jdk/pull/9451