我在JMH中看到ConstantFold的一个普遍问题,但是如果我有反问题怎么办。我需要静态的final字段作为参数。例如,对于某些算法,它可以是一些常量。
但是在java-doc中,我看到:{@link Param}字段应该是非最终字段。
我测试了静态参数(带有@Param批注)和静态final,我发现访问static final的效率提高了约1.5到2倍。
我发现了一个快速的解决方案:
private static final int SURROGATE = Runtime.getRuntime().availableProcessors(); //example
private static final Field SURROGATE_FIELD;
private static final String MODIFIERS_FIELD = "modifiers";
private static final ReflectionFactory reflection =
ReflectionFactory.getReflectionFactory();
private static final FieldAccessor SURROGATE_FIELD_ACCESSOR;
static {
try {
SURROGATE_FIELD = ConstantFinalFieldBench.class.getDeclaredField("SURROGATE");
SURROGATE_FIELD.setAccessible(true);
Field modifiersField =
Field.class.getDeclaredField(MODIFIERS_FIELD);
modifiersField.setAccessible(true);
int modifiers = modifiersField.getInt(SURROGATE_FIELD);
modifiers &= ~Modifier.FINAL;
modifiersField.setInt(SURROGATE_FIELD, modifiers);
SURROGATE_FIELD_ACCESSOR = reflection.newFieldAccessor(
SURROGATE_FIELD, false
);
} catch (Exception ex) {
throw new Error(ex);
}
}
@Param({"10"})
private static int paramConst;
@Setup
public void init() throws IllegalAccessException {
SURROGATE_FIELD_ACCESSOR.setInt(null, paramConst);
}
对“ SURROGATE”参数的访问具有性能,就像对最终字段一样。但是,也许我错过了一些东西,或者不知道,也许还有另一种方法?!否则将来会提供支持将是不错的选择。
最佳答案
您到底想完成什么?用可怕的反射黑客覆盖static finals
?祝你好运!您需要遵循语言规则,并使用静态初始化程序初始化static final
-s。
您无法在此处轻松地对值进行参数化,因为除了某些自定义的System.getProperty
调用之外,您无法将任何参数传递给静态初始值设定项,通常是通过这种方式完成的。 JMH不会公开任何API来轮询在静态最终初始化中可用的“当前”参数。
您可以尝试使用@State
创建一个static
类,但不使用final
字段,将参数放在该字段上,然后非常小心地触发另一个具有static final
字段的类的初始化,该类将查询字段。但是,这非常脆弱,可能会产生无法预料的后果。例如您将只能在每个JVM中完成一次此操作,并且随后在同一JVM中运行的所有操作都将默默地忽略“读取” static
。