- JIT编译器是否有办法在某个时间点后检测到if语句将始终为true?
是的,如果字段是static final
,并且它的持有类在JIT编译器启动时已被初始化。显然,在您的情况下不适用,因为Config.initialized
无法设置为static final
。
- 我能做些什么来支持这个吗?
java.lang.invoke.MutableCallSite
可以帮忙。
这个类专门设计用于您的需求。它的setTarget
方法支持在运行时重新绑定调用站点。在幕后,它会导致当前编译方法的去优化,并可能稍后重新编译它以使用新的目标。
可以使用dynamicInvoker
方法获取用于调用MutableCallSite
目标的MethodHandle
。请注意,MethodHandle
应该是static final
,以允许内联。
- 如果上述方法被内联到某个地方,则所有这些方法都将被重新编译
是的。
这里有一个基准测试,演示了mutableCallSite
方法在开头与alwaysFalse
一样快,切换后也与alwaysTrue
一样快。我还包括了一个静态字段toggle进行比较,如@Holger所建议的。
package bench;
import org.openjdk.jmh.annotations.*;
import java.lang.invoke.*;
import java.util.concurrent.*;
@State(Scope.Benchmark)
public class Toggle {
static boolean toggleField = false;
static final MutableCallSite toggleCallSite =
new MutableCallSite(MethodHandles.constant(boolean.class, false));
static final MethodHandle toggleMH = toggleCallSite.dynamicInvoker();
public void switchToggle() {
toggleField = true;
toggleCallSite.setTarget(MethodHandles.constant(boolean.class, true));
MutableCallSite.syncAll(new MutableCallSite[]{toggleCallSite});
System.out.print("*** Toggle switched *** ");
}
@Setup
public void init() {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.schedule(this::switchToggle, 10100, TimeUnit.MILLISECONDS);
executor.shutdown();
}
@Benchmark
public int alwaysFalse() {
return 0;
}
@Benchmark
public int alwaysTrue() {
return ThreadLocalRandom.current().nextInt();
}
@Benchmark
public int field() {
if (toggleField) {
return ThreadLocalRandom.current().nextInt();
} else {
return 0;
}
}
@Benchmark
public int mutableCallSite() throws Throwable {
if ((boolean) toggleMH.invokeExact()) {
return ThreadLocalRandom.current().nextInt();
} else {
return 0;
}
}
}
运行基准测试时,进行了5次预热迭代和10次测量迭代,我得到了以下结果:
# JMH version: 1.20
# VM version: JDK 1.8.0_192, VM 25.192-b12
# Benchmark: bench.Toggle.alwaysFalse
# Run progress: 0,00% complete, ETA 00:01:00
# Fork: 1 of 1
# Warmup Iteration 1: 3,875 ns/op
# Warmup Iteration 2: 3,369 ns/op
# Warmup Iteration 3: 2,699 ns/op
# Warmup Iteration 4: 2,696 ns/op
# Warmup Iteration 5: 2,703 ns/op
Iteration 1: 2,697 ns/op
Iteration 2: 2,696 ns/op
Iteration 3: 2,696 ns/op
Iteration 4: 2,706 ns/op
Iteration 5: *** Toggle switched *** 2,698 ns/op
Iteration 6: 2,698 ns/op
Iteration 7: 2,692 ns/op
Iteration 8: 2,707 ns/op
Iteration 9: 2,712 ns/op
Iteration 10: 2,702 ns/op
# Benchmark: bench.Toggle.alwaysTrue
# Run progress: 25,00% complete, ETA 00:00:48
# Fork: 1 of 1
# Warmup Iteration 1: 5,159 ns/op
# Warmup Iteration 2: 5,198 ns/op
# Warmup Iteration 3: 4,314 ns/op
# Warmup Iteration 4: 4,321 ns/op
# Warmup Iteration 5: 4,306 ns/op
Iteration 1: 4,306 ns/op
Iteration 2: 4,310 ns/op
Iteration 3: 4,297 ns/op
Iteration 4: 4,324 ns/op
Iteration 5: *** Toggle switched *** 4,356 ns/op
Iteration 6: 4,300 ns/op
Iteration 7: 4,310 ns/op
Iteration 8: 4,290 ns/op
Iteration 9: 4,297 ns/op
Iteration 10: 4,294 ns/op
# Benchmark: bench.Toggle.field
# Run progress: 50,00% complete, ETA 00:00:32
# Fork: 1 of 1
# Warmup Iteration 1: 3,596 ns/op
# Warmup Iteration 2: 3,429 ns/op
# Warmup Iteration 3: 2,973 ns/op
# Warmup Iteration 4: 2,937 ns/op
# Warmup Iteration 5: 2,934 ns/op
Iteration 1: 2,927 ns/op
Iteration 2: 2,928 ns/op
Iteration 3: 2,932 ns/op
Iteration 4: 2,929 ns/op
Iteration 5: *** Toggle switched *** 3,002 ns/op
Iteration 6: 4,887 ns/op
Iteration 7: 4,866 ns/op
Iteration 8: 4,877 ns/op
Iteration 9: 4,867 ns/op
Iteration 10: 4,877 ns/op
# Benchmark: bench.Toggle.mutableCallSite
# Run progress: 75,00% complete, ETA 00:00:16
# Fork: 1 of 1
# Warmup Iteration 1: 3,474 ns/op
# Warmup Iteration 2: 3,332 ns/op
# Warmup Iteration 3: 2,750 ns/op
# Warmup Iteration 4: 2,701 ns/op
# Warmup Iteration 5: 2,701 ns/op
Iteration 1: 2,697 ns/op
Iteration 2: 2,696 ns/op
Iteration 3: 2,699 ns/op
Iteration 4: 2,706 ns/op
Iteration 5: *** Toggle switched *** 2,771 ns/op
Iteration 6: 4,310 ns/op
Iteration 7: 4,306 ns/op
Iteration 8: 4,312 ns/op
Iteration 9: 4,317 ns/op
Iteration 10: 4,301 ns/op
initialized
是volatile
的吗? - Iłya BursovConfig
的声明。 - chrylis -cautiouslyoptimistic-