You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Ralph Goers (Jira)" <ji...@apache.org> on 2020/02/23 05:15:00 UTC

[jira] [Commented] (LOG4J2-2756) ClassLoaderContextSelector: WeakReference and GC

    [ https://issues.apache.org/jira/browse/LOG4J2-2756?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17042797#comment-17042797 ] 

Ralph Goers commented on LOG4J2-2756:
-------------------------------------

I considered replacing the problem code with
{code:java}
return CONTEXT_MAP.computeIfAbsent(name, k -> new AtomicReference<>(new WeakReference<>(createContext(name, configLocation)))).get().get();{code}
but from your description of the problem it seems the LoggerContext could be finalized before the call to get() is made so instead I am planning to do:
{code:java}
ContextHolder holder = new ContextHolder(createContext(name, configLocation));
holder.loggerContext = CONTEXT_MAP.computeIfAbsent(name, k -> new AtomicReference<>(new WeakReference<>(createContext(name, configLocation)))).get().get();
return holder.get();{code}

If I understand the issue correctly this should prevent the LoggerContext from being disposed of during the method since it is held in a strong reference throughout the method.

> ClassLoaderContextSelector: WeakReference and GC
> ------------------------------------------------
>
>                 Key: LOG4J2-2756
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-2756
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.13.0
>         Environment: The problem depends on the implemention of the WeakReference-check in the used garbage collection algorithm of the JVM.
> Examples of affected JVMs:
>  * OpenJ9 OpenJDK8U-jdk_x64_linux_openj9_8u232b09_openj9-0.17.0.tar.gz (in combination with log4j-core-2.13.0.jar)
>  * IBM JRE 1.8.0_221 z/OS (with log4j-2.8.1)
>  * OpenJ9 JDK8 linux_x86 2115.LT2 (with log4j-2.3)
>  * OpenJ9 JDK11 x86_mac 441.WL4 (with log4j-2.3)
>  * OpenJ9 JDK13 146 (https://ci.eclipse.org/openj9/job/Test_openjdk13_j9_extended.system_ppc64le_linux_Nightly/146/ with log4j-2.3)
>            Reporter: Sascha Rogmann
>            Priority: Major
>
> A race-condition between GC and WeakReference in ClassLoaderContextSelector can lead to a NPE in Log4jContextFactory.
> {code:java}
> Exception in thread "main" java.lang.NullPointerException
>     at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:152)
>     at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
>     at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
>     at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:602)
> {code}
> In org.apache.logging.log4j.core.selector.ClassLoaderContextSelector there is the following creation of a LoggerContext in method locateContext:
> {code:java}
>             LoggerContext ctx = createContext(name, configLocation);
>             final AtomicReference<WeakReference<LoggerContext>> r = new AtomicReference<>();
>             r.set(new WeakReference<>(ctx));
>             CONTEXT_MAP.putIfAbsent(name, r);
>             ctx = CONTEXT_MAP.get(name).get().get();
>             return ctx;
> {code}
> The created LoggerContext is stored in local variable ctx. After storing the LoggerContext into a WeakReference the local variable isn't read until overridden by a new value out of the CONTEXT_MAP. A garbage collection between creating the WeakReference and reading the CONTEXT_MAP might remove the LoggerContext.
> This leads to intermittent failures in JVMs like OpenJ9 which mark locals as not-an-object so they can be collected as soon as possible. See also: [https://github.com/eclipse/openj9/issues/4005]



--
This message was sent by Atlassian Jira
(v8.3.4#803005)