Как я могу решить LI_LAZY_INIT_UPDATE_STATIC? - PullRequest
0 голосов
/ 04 июля 2019

Я пытаюсь инициализировать 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 В отчете об обнаружении ошибок говорится, что ofMethod() имеет LI_LAZY_INIT_UPDATE_STATIC проблему.

Я понимаю, что он говорит. Я вижу, что эти два шага (назначение и настройка доступны) проблематичны в многопоточной среде.

Как я могу решить проблему? Должен ли я применить Двойная проверка блокировки ?

Или я должен поставить ofMethod() логику в ofHandle()?

1 Ответ

0 голосов
/ 05 июля 2019

Я отвечаю на свой вопрос.

Идея удержания ссылки на ленивый объект - плохая идея.

Даже с Двойной проверкой блокировки ,

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;
}

Любой может изменить состояние accessible.

Я получил следующий код, который не зависит ни от каких внешних переменных.

static Method ofMethod() {
    try {
        final Method ofMethod = ...;
        if (!ofMethod.isAccessible()) {
            ofMethod.setAccessible(true);
        }
        return ofMethod;
    } catch (final NoSuchMethodException nsme) {
        throw new RuntimeException(nsme);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...