我在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

08-06 06:07
查看更多