java - 如何解决 LI_LAZY_INIT_UPDATE_STATIC?

标签 java multithreading singleton class-visibility spotbugs

我正在尝试为上游库中的非公共(public)方法初始化 MethodHandle

private static Method OF_METHOD;

static Method ofMethod() {
    if (OF_METHOD == null) {
        try {
            OF_METHOD = RequestObject.class.getDeclaredMethod(
                    "of", Class.class, String.class, String.class,
                    Object.class, Object.class);
            if (!OF_METHOD.isAccessible()) {
                OF_METHOD.setAccessible(true);
            }
        } catch (final NoSuchMethodException nsme) {
            throw new RuntimeException(nsme);
        }
    }
    return OF_METHOD;
}

private static MethodHandle OF_HANDLE;

static MethodHandle ofHandle() {
    if (OF_HANDLE == null) {
        try {
            OF_HANDLE = MethodHandles.lookup().unreflect(ofMethod());
        } catch (final ReflectiveOperationException roe) {
            throw new RuntimeException(roe);
        }
    }
    return OF_HANDLE;
}

还有我的SpotBugs Bug Detecter 报告显示 ofMethod() 有一个 LI_LAZY_INIT_UPDATE_STATIC问题。

我明白它在说什么。我发现这两个步骤(分配和设置可访问)在多线程环境中是有问题的。

如何解决这个问题?我应该申请Double-checked locking

或者我应该将 ofMethod() 逻辑放入 ofHandle() 中?

最佳答案

我正在回答我自己的问题。

持有惰性对象引用的想法是一个坏主意。

即使有 Double-checked locking ,

private static volatile Method OF_METHOD;

static Method ofMethod() {
    Method ofMethod = OF_METHOD;
    if (ofMethod == null) {
        synchronized (JacksonRequest.class) {
            ofMethod = OF_METHOD;
            if (ofMethod == null) {
                try {
                    ofMethod = ...;
                } catch (final NoSuchMethodException nsme) {
                    throw new RuntimeException(nsme);
                }
                if (!ofMethod.isAccessible()) {
                    ofMethod.setAccessible(true);
                }
                OF_METHOD = ofMethod;
            }
        }
    }
    return ofMethod;
}

任何人都可以更改可访问状态。

我最终得到了以下不依赖于任何外部变量的代码。

static Method ofMethod() {
    try {
        final Method ofMethod = ...;
        if (!ofMethod.isAccessible()) {
            ofMethod.setAccessible(true);
        }
        return ofMethod;
    } catch (final NoSuchMethodException nsme) {
        throw new RuntimeException(nsme);
    }
}

关于java - 如何解决 LI_LAZY_INIT_UPDATE_STATIC?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56879515/

相关文章:

java - 单独的正则表达式匹配,但它们的并集不匹配

java - Azure Functions with java - 如何获取函数内写入的日志?

java - Android 在 SD 卡上写入文件时出现错误 : Open Failed eacces permission denied

multithreading - python中的并行化方法

c++ - 具有原子状态的单例模式

java - 由于三个开源项目 Apache Drill、Apache Hadoop 和 Elastic search 使用不同版本的 io.netty 导致依赖收敛错误

java - 在使用 Ehcache 刷新只读缓存之前,我需要锁定它吗?

java - 在线程中使用变量

java - Java 类加载是单线程的吗?

c++ - 如何在 VS2017 中允许单例构造函数重新进入/传递?