You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/10/16 06:33:39 UTC

[logging-log4j2] branch master updated (485848e4d3 -> f1ffe2aa8d)

This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


    from 485848e4d3 Adapt `log4j-script` tests to the module path
     new e5b8b3fef6 Fix variable naming inconsistency
     new c5d55239bb Add PluginEntry.Builder to simplify code generation
     new 3946b2febf Refactor LazyValue into subclasses
     new f1ffe2aa8d Reset LoggerContextFactory after test class when using ContextSelectorType annotation

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/log4j/config/XmlConfigurationTest.java  |  26 ++--
 .../java/org/apache/logging/log4j/LogManager.java  |   4 +-
 .../logging/log4j/message/ThreadDumpMessage.java   |  13 +-
 .../java/org/apache/logging/log4j/util/Lazy.java   |  65 ++++++++
 .../org/apache/logging/log4j/util/LazyUtil.java    | 171 +++++++++++++++++++++
 .../org/apache/logging/log4j/util/LazyValue.java   |  85 ----------
 .../apache/logging/log4j/util/PropertiesUtil.java  |   8 +-
 .../apache/logging/log4j/util/ServiceRegistry.java |  12 +-
 .../core/test/junit/ContextSelectorCallback.java   |  28 ++--
 .../logging/log4j/core/layout/GelfLayoutTest.java  |  19 ++-
 .../logging/log4j/core/layout/HtmlLayoutTest.java  |   4 +-
 .../log4j/core/layout/PatternLayoutTest.java       |   4 +-
 .../log4j/core/layout/Rfc5424LayoutTest.java       |  25 ++-
 .../log4j/core/layout/SyslogLayoutTest.java        |   4 +-
 .../log4j/core/config/AbstractConfiguration.java   |   4 +-
 .../core/config/DefaultConfigurationFactory.java   |  17 +-
 .../lookup/JmxRuntimeInputArgumentsLookup.java     |   7 +-
 .../core/net/ssl/SslConfigurationFactory.java      |   8 +-
 .../log4j/core/selector/BasicContextSelector.java  |  14 +-
 .../core/selector/ClassLoaderContextSelector.java  |   6 +-
 .../logging/log4j/core/time/ClockFactory.java      |   7 +-
 .../log4j/core/time/internal/CachedClock.java      |   7 +-
 .../core/time/internal/CoarseCachedClock.java      |   7 +-
 .../apache/logging/log4j/core/util/JsonUtils.java  |   8 +-
 .../log4j/csv/layout/CsvLogEventLayoutTest.java    |   4 +-
 .../log4j/jackson/json/layout/JsonLayoutTest.java  |   4 +-
 .../log4j/jackson/xml/layout/XmlLayoutTest.java    |   4 +-
 .../log4j/jackson/yaml/layout/YamlLayoutTest.java  |   4 +-
 .../layout/template/json/util/JsonWriter.java      |   9 +-
 .../log4j/plugin/processor/PluginProcessor.java    |  65 ++------
 .../logging/log4j/plugins/di/DefaultInjector.java  |  46 +++---
 .../logging/log4j/plugins/model/PluginEntry.java   |  48 +-----
 .../log4j/plugins/model/PluginRegistry.java        |  22 +--
 .../logging/log4j/plugins/model/PluginType.java    |  30 +---
 34 files changed, 417 insertions(+), 372 deletions(-)
 create mode 100644 log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java
 create mode 100644 log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java
 delete mode 100644 log4j-api/src/main/java/org/apache/logging/log4j/util/LazyValue.java


[logging-log4j2] 02/04: Add PluginEntry.Builder to simplify code generation

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit c5d55239bba6c9e209d079d71bd3f5c96927fb3e
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Oct 15 15:50:40 2022 -0500

    Add PluginEntry.Builder to simplify code generation
    
    This updates PluginProcessor to use the builder class while removing the implemented interfaces property from PluginEntry.
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../log4j/plugin/processor/PluginProcessor.java    | 65 +++++-----------------
 .../logging/log4j/plugins/di/DefaultInjector.java  | 40 ++++++-------
 .../logging/log4j/plugins/model/PluginEntry.java   | 48 ++--------------
 .../logging/log4j/plugins/model/PluginType.java    | 18 +-----
 4 files changed, 40 insertions(+), 131 deletions(-)

diff --git a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
index c991ce8f45..87eb4197b7 100644
--- a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
+++ b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java
@@ -34,16 +34,10 @@ import javax.lang.model.SourceVersion;
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementKindVisitor9;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.SimpleElementVisitor8;
-import javax.lang.model.util.SimpleTypeVisitor9;
-import javax.lang.model.util.Types;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.FileObject;
 import javax.tools.JavaFileObject;
@@ -55,7 +49,6 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -170,33 +163,27 @@ public class PluginProcessor extends AbstractProcessor {
             writer.println("");
             writer.println("public class Log4jPlugins extends PluginService {");
             writer.println("");
-            writer.println("    private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
-            StringBuilder sb = new StringBuilder();
+            writer.println("  private static final PluginEntry[] ENTRIES = new PluginEntry[] {");
             int max = list.size() - 1;
             for (int i = 0; i < list.size(); ++i) {
                 PluginEntryMirror mirror = list.get(i);
                 final PluginEntry entry = mirror.entry;
-                sb.append("        ").append("new PluginEntry(\"");
-                sb.append(entry.getKey()).append("\", \"");
-                sb.append(entry.getClassName()).append("\", \"");
-                sb.append(entry.getName()).append("\", \"");
-                final String elementName = entry.getElementType();
-                if (elementName != null) {
-                    sb.append(elementName);
+                writer.println("    PluginEntry.builder()");
+                writer.println(String.format("      .setKey(\"%s\")", entry.getKey()));
+                writer.println(String.format("      .setClassName(\"%s\")", entry.getClassName()));
+                writer.println(String.format("      .setName(\"%s\")", entry.getName()));
+                writer.println(String.format("      .setNamespace(\"%s\")", entry.getNamespace()));
+                final String elementType = entry.getElementType();
+                if (Strings.isNotEmpty(elementType)) {
+                    writer.println(String.format("      .setElementType(\"%s\")", elementType));
                 }
-                sb.append("\", ");
-                sb.append(entry.isPrintable()).append(", ");
-                sb.append(entry.isDeferChildren()).append(", \"");
-                sb.append(entry.getNamespace()).append("\"");
-                for (final Name implementedInterface : getImplementedInterfaces(mirror.element.asType())) {
-                    sb.append(", ").append(implementedInterface).append(".class");
+                if (entry.isPrintable()) {
+                    writer.println("      .setPrintable(true)");
                 }
-                sb.append(')');
-                if (i < max) {
-                    sb.append(",");
+                if (entry.isDeferChildren()) {
+                    writer.println("      .setDeferChildren(true)");
                 }
-                writer.println(sb);
-                sb.setLength(0);
+                writer.println("      .get()" + (i < max ? "," : Strings.EMPTY));
             }
             writer.println("    };");
             writer.println("    @Override");
@@ -274,30 +261,6 @@ public class PluginProcessor extends AbstractProcessor {
         }
     }
 
-    private Set<Name> getImplementedInterfaces(final TypeMirror base) {
-        final Set<Name> implementedInterfaces = new LinkedHashSet<>();
-        final Types types = processingEnv.getTypeUtils();
-        base.accept(new SimpleTypeVisitor9<Void, Void>() {
-            @Override
-            public Void visitDeclared(final DeclaredType t, final Void unused) {
-                for (final TypeMirror directSupertype : types.directSupertypes(t)) {
-                    directSupertype.accept(this, null);
-                }
-                t.asElement().accept(new ElementKindVisitor9<Void, Void>() {
-                    @Override
-                    public Void visitTypeAsInterface(final TypeElement e, final Void unused) {
-                        if (e.getModifiers().contains(Modifier.PUBLIC)) {
-                            implementedInterfaces.add(e.getQualifiedName());
-                        }
-                        return null;
-                    }
-                }, null);
-                return null;
-            }
-        }, null);
-        return implementedInterfaces;
-    }
-
     private String commonPrefix(String str1, String str2) {
         int minLength = Math.min(str1.length(), str2.length());
         for (int i = 0; i < minLength; i++) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index e930f33ded..c61f10df99 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -319,10 +319,8 @@ class DefaultInjector implements Injector {
         }
         final PluginNamespace namespace = getInstance(PluginRegistry.class).getNamespace(itemKey.getNamespace(), getPluginPackages());
         final Type type = itemKey.getType();
-        final Class<T> rawType = itemKey.getRawType();
         return namespace.stream()
-                .filter(pluginType -> rawType.isInterface() && pluginType.getImplementedInterfaces().contains(rawType) ||
-                        TypeUtil.isAssignable(type, pluginType.getPluginClass()))
+                .filter(pluginType -> TypeUtil.isAssignable(type, pluginType.getPluginClass()))
                 .sorted(Comparator.comparing(PluginType::getPluginClass, OrderedComparator.INSTANCE))
                 .map(TypeUtil::cast);
     }
@@ -574,22 +572,7 @@ class DefaultInjector implements Injector {
                 .allMatch(condition -> condition.matches(key, rawType))) {
             return null;
         }
-        final Executable factory = Stream.of(rawType.getDeclaredMethods())
-                .filter(method -> Modifier.isStatic(method.getModifiers()) &&
-                        AnnotationUtil.isMetaAnnotationPresent(method, FactoryType.class))
-                .min(Comparator.comparingInt(Method::getParameterCount).thenComparing(Method::getReturnType, (c1, c2) -> {
-                    if (c1.equals(c2)) {
-                        return 0;
-                    } else if (Supplier.class.isAssignableFrom(c1)) {
-                        return -1;
-                    } else if (Supplier.class.isAssignableFrom(c2)) {
-                        return 1;
-                    } else {
-                        return c1.getName().compareTo(c2.getName());
-                    }
-                }))
-                .map(Executable.class::cast)
-                .orElseGet(() -> getInjectableConstructor(key, Set.of()));
+        final Executable factory = getInjectablePluginFactory(rawType);
         final List<InjectionPoint<?>> points = InjectionPoint.fromExecutable(factory);
         if (!factory.canAccess(null)) {
             accessor.makeAccessible(factory);
@@ -783,6 +766,25 @@ class DefaultInjector implements Injector {
         return newChain;
     }
 
+    private static Executable getInjectablePluginFactory(final Class<?> pluginClass) {
+        return Stream.of(pluginClass.getDeclaredMethods())
+                .filter(method -> Modifier.isStatic(method.getModifiers()) &&
+                        AnnotationUtil.isMetaAnnotationPresent(method, FactoryType.class))
+                .min(Comparator.comparingInt(Method::getParameterCount).thenComparing(Method::getReturnType, (c1, c2) -> {
+                    if (c1.equals(c2)) {
+                        return 0;
+                    } else if (Supplier.class.isAssignableFrom(c1)) {
+                        return -1;
+                    } else if (Supplier.class.isAssignableFrom(c2)) {
+                        return 1;
+                    } else {
+                        return c1.getName().compareTo(c2.getName());
+                    }
+                }))
+                .map(Executable.class::cast)
+                .orElseGet(() -> getInjectableConstructor(Key.forClass(pluginClass), Set.of()));
+    }
+
     private static <T> Constructor<T> getInjectableConstructor(final Key<T> key, final Set<Key<?>> chain) {
         final Class<T> rawType = key.getRawType();
         final List<Constructor<?>> injectConstructors = Stream.of(rawType.getDeclaredConstructors())
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
index f9e240e745..fb507b4dbc 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginEntry.java
@@ -17,6 +17,8 @@
 
 package org.apache.logging.log4j.plugins.model;
 
+import org.apache.logging.log4j.util.Strings;
+
 import java.util.function.Supplier;
 
 /**
@@ -30,32 +32,6 @@ public class PluginEntry {
     private final boolean printable;
     private final boolean deferChildren;
     private final String namespace;
-    private final Class<?>[] interfaces;
-
-    public PluginEntry(
-            String key, String className, String name, String elementType, boolean printable, boolean deferChildren, String namespace) {
-        this.key = key;
-        this.className = className;
-        this.name = name;
-        this.elementType = elementType;
-        this.printable = printable;
-        this.deferChildren = deferChildren;
-        this.namespace = namespace;
-        this.interfaces = null;
-    }
-
-    public PluginEntry(
-            final String key, final String className, final String name, final String elementType, final boolean printable,
-            final boolean deferChildren, final String namespace, final Class<?>... interfaces) {
-        this.key = key;
-        this.className = className;
-        this.name = name;
-        this.elementType = elementType;
-        this.printable = printable;
-        this.deferChildren = deferChildren;
-        this.namespace = namespace;
-        this.interfaces = interfaces;
-    }
 
     private PluginEntry(final Builder builder) {
         key = builder.getKey();
@@ -65,8 +41,6 @@ public class PluginEntry {
         printable = builder.isPrintable();
         deferChildren = builder.isDeferChildren();
         namespace = builder.getNamespace();
-        final Class<?>[] classes = builder.getInterfaces();
-        interfaces = classes != null ? classes.clone() : null;
     }
 
     public String getKey() {
@@ -97,10 +71,6 @@ public class PluginEntry {
         return namespace;
     }
 
-    public Class<?>[] getInterfaces() {
-        return interfaces;
-    }
-
     @Override
     public String toString() {
         return "PluginEntry [key=" + key + ", className=" + className + ", name=" + name + ", printable=" + printable
@@ -115,11 +85,10 @@ public class PluginEntry {
         private String key;
         private String className;
         private String name;
-        private String elementType;
+        private String elementType = Strings.EMPTY;
         private boolean printable;
         private boolean deferChildren;
-        private String namespace;
-        private Class<?>[] interfaces;
+        private String namespace = Strings.EMPTY;
 
         public String getKey() {
             return key;
@@ -184,15 +153,6 @@ public class PluginEntry {
             return this;
         }
 
-        public Class<?>[] getInterfaces() {
-            return interfaces;
-        }
-
-        public Builder setInterfaces(final Class<?>... interfaces) {
-            this.interfaces = interfaces;
-            return this;
-        }
-
         @Override
         public PluginEntry get() {
             return new PluginEntry(this);
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
index 0c8bbcd7cd..028d56ee77 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.plugins.model;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.util.LazyValue;
 
-import java.util.Set;
 import java.util.function.Supplier;
 
 /**
@@ -32,7 +31,6 @@ public class PluginType<T> {
 
     private final PluginEntry pluginEntry;
     private final Supplier<Class<T>> pluginClass;
-    private final Supplier<Set<Class<?>>> implementedInterfaces;
 
     /**
      * Constructor.
@@ -44,8 +42,6 @@ public class PluginType<T> {
             final PluginEntry pluginEntry, final Class<T> pluginClass) {
         this.pluginEntry = pluginEntry;
         this.pluginClass = () -> pluginClass;
-        final var interfaces = Set.of(pluginClass.getInterfaces());
-        this.implementedInterfaces = () -> interfaces;
     }
 
     /**
@@ -55,7 +51,7 @@ public class PluginType<T> {
      */
     public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
         this.pluginEntry = pluginEntry;
-        final LazyValue<Class<T>> classProvider = LazyValue.from(() -> {
+        this.pluginClass = LazyValue.from(() -> {
             try {
                 return TypeUtil.cast(classLoader.loadClass(pluginEntry.getClassName()));
             } catch (final ClassNotFoundException e) {
@@ -63,14 +59,6 @@ public class PluginType<T> {
                         " located for element " + pluginEntry.getName(), e);
             }
         });
-        this.pluginClass = classProvider;
-        final Class<?>[] interfaces = pluginEntry.getInterfaces();
-        if (interfaces != null) {
-            final var implementedInterfaces = Set.of(interfaces);
-            this.implementedInterfaces = () -> implementedInterfaces;
-        } else {
-            this.implementedInterfaces = classProvider.map(clazz -> Set.of(clazz.getInterfaces()));
-        }
     }
 
     public PluginEntry getPluginEntry() {
@@ -81,10 +69,6 @@ public class PluginType<T> {
         return pluginClass.get();
     }
 
-    public Set<Class<?>> getImplementedInterfaces() {
-        return implementedInterfaces.get();
-    }
-
     public String getElementType() {
         return pluginEntry.getElementType();
     }


[logging-log4j2] 01/04: Fix variable naming inconsistency

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit e5b8b3fef663250db871f758f1bb1d42e698267e
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 9 17:07:32 2022 -0500

    Fix variable naming inconsistency
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../logging/log4j/plugins/model/PluginRegistry.java      | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
index fb6f4a15a6..f77e82d1d7 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
@@ -314,18 +314,18 @@ public class PluginRegistry {
      * Bundles plugins by namespace from a plugin source.
      */
     private static class Namespaces implements Iterable<PluginNamespace> {
-        private final Map<String, PluginNamespace> categories;
+        private final Map<String, PluginNamespace> namespaces;
 
         private Namespaces() {
-            categories = new LinkedHashMap<>();
+            namespaces = new LinkedHashMap<>();
         }
 
-        private Namespaces(final Map<String, PluginNamespace> categories) {
-            this.categories = categories;
+        private Namespaces(final Map<String, PluginNamespace> namespaces) {
+            this.namespaces = namespaces;
         }
 
         public boolean isEmpty() {
-            return categories.isEmpty();
+            return namespaces.isEmpty();
         }
 
         public int merge(final PluginNamespace category) {
@@ -344,16 +344,16 @@ public class PluginRegistry {
         }
 
         public PluginNamespace get(final String category) {
-            return categories.get(category.toLowerCase(Locale.ROOT));
+            return namespaces.get(category.toLowerCase(Locale.ROOT));
         }
 
         public PluginNamespace getOrCreate(final String category) {
-            return categories.computeIfAbsent(category.toLowerCase(Locale.ROOT), key -> new PluginNamespace(key, category));
+            return namespaces.computeIfAbsent(category.toLowerCase(Locale.ROOT), key -> new PluginNamespace(key, category));
         }
 
         @Override
         public Iterator<PluginNamespace> iterator() {
-            return categories.values().iterator();
+            return namespaces.values().iterator();
         }
     }
 }


[logging-log4j2] 04/04: Reset LoggerContextFactory after test class when using ContextSelectorType annotation

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit f1ffe2aa8d0f3ccd5b79ffb9b1ba771f51bbc6da
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 16 01:32:59 2022 -0500

    Reset LoggerContextFactory after test class when using ContextSelectorType annotation
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../core/test/junit/ContextSelectorCallback.java   | 28 ++++++++++++++--------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ContextSelectorCallback.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ContextSelectorCallback.java
index 14cff75071..75f339e981 100644
--- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ContextSelectorCallback.java
+++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ContextSelectorCallback.java
@@ -22,20 +22,28 @@ import org.apache.logging.log4j.core.impl.Log4jContextFactory;
 import org.apache.logging.log4j.core.selector.ContextSelector;
 import org.apache.logging.log4j.plugins.di.DI;
 import org.apache.logging.log4j.plugins.di.Injector;
+import org.junit.jupiter.api.extension.AfterAllCallback;
 import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.support.AnnotationSupport;
 
-public class ContextSelectorCallback implements BeforeAllCallback {
+public class ContextSelectorCallback implements BeforeAllCallback, AfterAllCallback {
     @Override
     public void beforeAll(final ExtensionContext context) throws Exception {
-        final Class<?> testClass = context.getRequiredTestClass();
-        final ContextSelectorType source = testClass.getAnnotation(ContextSelectorType.class);
-        if (source != null) {
-            final Injector injector = DI.createInjector();
-            injector.registerBinding(ContextSelector.KEY, injector.getFactory(source.value()));
-            injector.init();
-            final Log4jContextFactory factory = injector.getInstance(Log4jContextFactory.class);
-            LogManager.setFactory(factory);
-        }
+        AnnotationSupport.findAnnotation(context.getTestClass(), ContextSelectorType.class)
+                .map(ContextSelectorType::value)
+                .ifPresent(contextSelectorClass -> {
+                    final Injector injector = DI.createInjector();
+                    injector.registerBinding(ContextSelector.KEY, injector.getFactory(contextSelectorClass));
+                    injector.init();
+                    final Log4jContextFactory factory = injector.getInstance(Log4jContextFactory.class);
+                    LogManager.setFactory(factory);
+                });
+    }
+
+    @Override
+    public void afterAll(final ExtensionContext context) throws Exception {
+        AnnotationSupport.findAnnotation(context.getTestClass(), ContextSelectorType.class)
+                .ifPresent(ignored -> LogManager.setFactory(null));
     }
 }


[logging-log4j2] 03/04: Refactor LazyValue into subclasses

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 3946b2febfb7f9cd3b048d0bab0edd3d83a89134
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 16 01:31:54 2022 -0500

    Refactor LazyValue into subclasses
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../apache/log4j/config/XmlConfigurationTest.java  |  26 ++--
 .../java/org/apache/logging/log4j/LogManager.java  |   4 +-
 .../logging/log4j/message/ThreadDumpMessage.java   |  13 +-
 .../java/org/apache/logging/log4j/util/Lazy.java   |  65 ++++++++
 .../org/apache/logging/log4j/util/LazyUtil.java    | 171 +++++++++++++++++++++
 .../org/apache/logging/log4j/util/LazyValue.java   |  85 ----------
 .../apache/logging/log4j/util/PropertiesUtil.java  |   8 +-
 .../apache/logging/log4j/util/ServiceRegistry.java |  12 +-
 .../logging/log4j/core/layout/GelfLayoutTest.java  |  19 ++-
 .../logging/log4j/core/layout/HtmlLayoutTest.java  |   4 +-
 .../log4j/core/layout/PatternLayoutTest.java       |   4 +-
 .../log4j/core/layout/Rfc5424LayoutTest.java       |  25 ++-
 .../log4j/core/layout/SyslogLayoutTest.java        |   4 +-
 .../log4j/core/config/AbstractConfiguration.java   |   4 +-
 .../core/config/DefaultConfigurationFactory.java   |  17 +-
 .../lookup/JmxRuntimeInputArgumentsLookup.java     |   7 +-
 .../core/net/ssl/SslConfigurationFactory.java      |   8 +-
 .../log4j/core/selector/BasicContextSelector.java  |  14 +-
 .../core/selector/ClassLoaderContextSelector.java  |   6 +-
 .../logging/log4j/core/time/ClockFactory.java      |   7 +-
 .../log4j/core/time/internal/CachedClock.java      |   7 +-
 .../core/time/internal/CoarseCachedClock.java      |   7 +-
 .../apache/logging/log4j/core/util/JsonUtils.java  |   8 +-
 .../log4j/csv/layout/CsvLogEventLayoutTest.java    |   4 +-
 .../log4j/jackson/json/layout/JsonLayoutTest.java  |   4 +-
 .../log4j/jackson/xml/layout/XmlLayoutTest.java    |   4 +-
 .../log4j/jackson/yaml/layout/YamlLayoutTest.java  |   4 +-
 .../layout/template/json/util/JsonWriter.java      |   9 +-
 .../logging/log4j/plugins/di/DefaultInjector.java  |   6 +-
 .../log4j/plugins/model/PluginRegistry.java        |   6 +-
 .../logging/log4j/plugins/model/PluginType.java    |  14 +-
 31 files changed, 352 insertions(+), 224 deletions(-)

diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
index f567d26938..6ba0391ddb 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
@@ -16,17 +16,6 @@
  */
 package org.apache.log4j.config;
 
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.log4j.ListAppender;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
@@ -38,10 +27,21 @@ import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 /**
  * Test configuration from XML.
  */
@@ -56,7 +56,7 @@ public class XmlConfigurationTest extends AbstractLog4j1ConfigurationTest {
         final ConfigurationSource source = new ConfigurationSource(inputStream);
         final LoggerContext context = LoggerContext.getContext(false);
         final Configuration configuration = context.getInjector()
-                .registerBinding(ConfigurationFactory.KEY, new LazyValue<>(XmlConfigurationFactory::new))
+                .registerBinding(ConfigurationFactory.KEY, Lazy.lazy(XmlConfigurationFactory::new))
                 .getInstance(ConfigurationFactory.KEY)
                 .getConfiguration(context, source);
         assertNotNull(configuration, "No configuration created");
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
index c2d6b46811..aaf1ba84c8 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.spi.LoggerContextFactory;
 import org.apache.logging.log4j.spi.Provider;
 import org.apache.logging.log4j.spi.Terminable;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.LoaderUtil;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.ProviderUtil;
@@ -68,7 +68,7 @@ public class LogManager {
      * Scans the classpath to find all logging implementation. Currently, only one will be used but this could be
      * extended to allow multiple implementations to be used.
      */
-    private static final LazyValue<LoggerContextFactory> PROVIDER = LazyValue.from(() -> {
+    private static final Lazy<LoggerContextFactory> PROVIDER = Lazy.lazy(() -> {
         // Shortcut binding to force a specific logging implementation.
         final PropertiesUtil managerProps = PropertiesUtil.getProperties();
         final String factoryClassName = managerProps.getStringProperty(FACTORY_PROPERTY_NAME);
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
index 07c35b2dbd..2bf80736a1 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
@@ -16,18 +16,17 @@
  */
 package org.apache.logging.log4j.message;
 
+import org.apache.logging.log4j.util.Lazy;
+import org.apache.logging.log4j.util.ServiceRegistry;
+import org.apache.logging.log4j.util.StringBuilderFormattable;
+import org.apache.logging.log4j.util.Strings;
+
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.lang.invoke.MethodHandles;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.function.Supplier;
-
-import org.apache.logging.log4j.util.LazyValue;
-import org.apache.logging.log4j.util.ServiceRegistry;
-import org.apache.logging.log4j.util.StringBuilderFormattable;
-import org.apache.logging.log4j.util.Strings;
 
 /**
  * Captures information about all running Threads.
@@ -35,7 +34,7 @@ import org.apache.logging.log4j.util.Strings;
 @AsynchronouslyFormattable
 public class ThreadDumpMessage implements Message, StringBuilderFormattable {
     private static final long serialVersionUID = -1103400781608841088L;
-    private static final Supplier<ThreadInfoFactory> FACTORY = new LazyValue<>(() -> {
+    private static final Lazy<ThreadInfoFactory> FACTORY = Lazy.lazy(() -> {
         final var services = ServiceRegistry.getInstance()
                 .getServices(ThreadInfoFactory.class, MethodHandles.lookup(), null);
         return services.isEmpty() ? new BasicThreadInfoFactory() : services.get(0);
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java
new file mode 100644
index 0000000000..b91456d552
--- /dev/null
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.util;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Provides a lazily-initialized value from a {@code Supplier<T>}.
+ *
+ * @param <T> type of value
+ */
+public interface Lazy<T> extends Supplier<T> {
+    T value();
+
+    @Override
+    default T get() {
+        return value();
+    }
+
+    default <R> Lazy<R> map(final Function<? super T, ? extends R> function) {
+        return lazy(() -> function.apply(value()));
+    }
+
+    boolean isInitialized();
+
+    void set(final T newValue);
+
+    /**
+     * Creates a lazy value using the provided Supplier for initialization guarded by a Lock.
+     */
+    static <T> Lazy<T> lazy(final Supplier<T> supplier) {
+        return new LazyUtil.SafeLazy<>(supplier);
+    }
+
+    /**
+     * Creates a lazy value using the provided constant value.
+     */
+    static <T> Lazy<T> value(final T value) {
+        return new LazyUtil.Constant<>(value);
+    }
+
+    /**
+     * Creates a relaxed lazy value using the provided Supplier for initialization which may be invoked more than once
+     * in order to set the initialized value.
+     */
+    static <T> Lazy<T> relaxed(final Supplier<T> supplier) {
+        return new LazyUtil.ReleaseAcquireLazy<>(supplier);
+    }
+}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java
new file mode 100644
index 0000000000..7f15a0bb42
--- /dev/null
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.util;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
+
+final class LazyUtil {
+    private static final Object NULL = new Object() {
+        @Override
+        public String toString() {
+            return "null";
+        }
+    };
+
+    static Object wrapNull(final Object value) {
+        return value == null ? NULL : value;
+    }
+
+    static <T> T unwrapNull(final Object value) {
+        return value == NULL ? null : cast(value);
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> T cast(final Object o) {
+        return (T) o;
+    }
+
+    static class Constant<T> implements Lazy<T> {
+        private final T value;
+
+        Constant(final T value) {
+            this.value = value;
+        }
+
+        @Override
+        public T value() {
+            return value;
+        }
+
+        @Override
+        public boolean isInitialized() {
+            return true;
+        }
+
+        @Override
+        public void set(final T newValue) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String toString() {
+            return String.valueOf(value);
+        }
+    }
+
+    static class SafeLazy<T> implements Lazy<T> {
+        private final Lock lock = new ReentrantLock();
+        private final Supplier<T> supplier;
+        private volatile Object value;
+
+        SafeLazy(final Supplier<T> supplier) {
+            this.supplier = supplier;
+        }
+
+        @Override
+        public T value() {
+            Object value = this.value;
+            if (value == null) {
+                lock.lock();
+                try {
+                    value = this.value;
+                    if (value == null) {
+                        value = supplier.get();
+                        this.value = wrapNull(value);
+                    }
+                } finally {
+                    lock.unlock();
+                }
+            }
+            return unwrapNull(value);
+        }
+
+        @Override
+        public void set(final T newValue) {
+            value = newValue;
+        }
+
+        public void reset() {
+            value = null;
+        }
+
+        @Override
+        public boolean isInitialized() {
+            return value != null;
+        }
+
+        @Override
+        public String toString() {
+            return isInitialized() ? String.valueOf(value) : "Lazy value not initialized";
+        }
+    }
+
+    static class ReleaseAcquireLazy<T> implements Lazy<T> {
+        private static final VarHandle VALUE;
+        static {
+            try {
+                VALUE = MethodHandles.lookup()
+                        .findVarHandle(ReleaseAcquireLazy.class, "value", Object.class);
+            } catch (NoSuchFieldException | IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        private final Supplier<T> supplier;
+        private volatile Object value;
+
+        ReleaseAcquireLazy(final Supplier<T> supplier) {
+            this.supplier = supplier;
+        }
+
+        @Override
+        public T value() {
+            final var currentValue = VALUE.getAcquire(this);
+            if (currentValue != null) {
+                return unwrapNull(currentValue);
+            }
+            final T newValue = supplier.get();
+            if (VALUE.compareAndSet(this, (Object) null, wrapNull(newValue))) {
+                return newValue;
+            }
+            final Object value = VALUE.getAcquire(this);
+            return unwrapNull(value);
+        }
+
+        @Override
+        public void set(final T newValue) {
+            // equivalent to VALUE.setVolatile(this, newValue)
+            value = newValue;
+        }
+
+        @Override
+        public boolean isInitialized() {
+            final var current = VALUE.getAcquire(this);
+            return current != null;
+        }
+
+        @Override
+        public String toString() {
+            return isInitialized() ? String.valueOf(VALUE.getOpaque(value)) : "Lazy value not initialized";
+        }
+    }
+}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyValue.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyValue.java
deleted file mode 100644
index 20d7965e64..0000000000
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyValue.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.util;
-
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * Provides a lazily-initialized value from a {@code Supplier<T>}.
- *
- * @param <T> type of value
- */
-public final class LazyValue<T> implements Supplier<T> {
-
-    private static final Object NULL_INSTANCE = new Object();
-
-    @SuppressWarnings("unchecked")
-    private static <T> T nullInstance() {
-        return (T) NULL_INSTANCE;
-    }
-
-    /**
-     * Creates a lazy value using the provided Supplier for initialization.
-     */
-    public static <T> LazyValue<T> from(final Supplier<T> supplier) {
-        return new LazyValue<>(supplier);
-    }
-
-    private final Supplier<T> supplier;
-    private volatile T value;
-
-    /**
-     * Constructs a lazy value using the provided Supplier for initialization.
-     *
-     * @param supplier value to lazily initialize
-     */
-    public LazyValue(final Supplier<T> supplier) {
-        this.supplier = supplier;
-    }
-
-    @Override
-    public T get() {
-        T value = this.value;
-        if (value == null) {
-            synchronized (this) {
-                value = this.value;
-                if (value == null) {
-                    value = supplier.get();
-                    this.value = value == null ? nullInstance() : value;
-                }
-            }
-        }
-        return value == NULL_INSTANCE ? null : value;
-    }
-
-    public void set(final T value) {
-        this.value = value;
-    }
-
-    /**
-     * Creates a LazyValue that maps the result of this LazyValue to another value.
-     *
-     * @param function mapping function to transform the result of this lazy value
-     * @param <R>      the return type of the new lazy value
-     * @return the new lazy value
-     */
-    public <R> LazyValue<R> map(final Function<? super T, ? extends R> function) {
-        return from(() -> function.apply(get()));
-    }
-}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index 699de74250..1f215de209 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.util;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
 import java.nio.charset.Charset;
 import java.time.Duration;
 import java.time.temporal.ChronoUnit;
@@ -33,7 +32,6 @@ import java.util.Properties;
 import java.util.ResourceBundle;
 import java.util.ServiceLoader;
 import java.util.Set;
-import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListSet;
 
@@ -54,8 +52,8 @@ public final class PropertiesUtil {
 
     private static final String LOG4J_PROPERTIES_FILE_NAME = "log4j2.component.properties";
     private static final String LOG4J_SYSTEM_PROPERTIES_FILE_NAME = "log4j2.system.properties";
-    private static final LazyValue<PropertiesUtil> COMPONENT_PROPERTIES =
-            LazyValue.from(() -> new PropertiesUtil(LOG4J_PROPERTIES_FILE_NAME));
+    private static final Lazy<PropertiesUtil> COMPONENT_PROPERTIES =
+            Lazy.lazy(() -> new PropertiesUtil(LOG4J_PROPERTIES_FILE_NAME));
 
     private final Environment environment;
 
@@ -121,7 +119,7 @@ public final class PropertiesUtil {
      * @return the main Log4j PropertiesUtil instance.
      */
     public static PropertiesUtil getProperties() {
-        return COMPONENT_PROPERTIES.get();
+        return COMPONENT_PROPERTIES.value();
     }
 
     /**
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java
index 23f55b6b16..f52859a5db 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceRegistry.java
@@ -24,10 +24,11 @@ import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Predicate;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static org.apache.logging.log4j.util.LazyUtil.cast;
+
 /**
  * Registry for service instances loaded from {@link ServiceLoader}. This abstracts the differences between using a flat
  * classpath, a module path, and OSGi modules.
@@ -35,7 +36,7 @@ import java.util.stream.Stream;
  * @since 3.0.0
  */
 public class ServiceRegistry {
-    private static final Supplier<ServiceRegistry> INSTANCE = new LazyValue<>(ServiceRegistry::new);
+    private static final Lazy<ServiceRegistry> INSTANCE = Lazy.relaxed(ServiceRegistry::new);
 
     /**
      * Returns the singleton ServiceRegistry instance.
@@ -44,11 +45,6 @@ public class ServiceRegistry {
         return INSTANCE.get();
     }
 
-    @SuppressWarnings("unchecked")
-    private static <T> T cast(final Object o) {
-        return (T) o;
-    }
-
     private final Map<Class<?>, List<?>> mainServices = new ConcurrentHashMap<>();
     private final Map<Long, Map<Class<?>, List<?>>> bundleServices = new ConcurrentHashMap<>();
 
@@ -61,7 +57,7 @@ public class ServiceRegistry {
      * load services.
      *
      * @param serviceType         service class
-     * @param loaderCallerContext function located in same module as caller context
+     * @param lookup              MethodHandle lookup created in same module as caller context
      *                            to use for loading services
      * @param validator           if non-null, used to validate service instances,
      *                            removing invalid instances from the returned list
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
index 5bbb540d2f..28941a49b8 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
@@ -16,13 +16,7 @@
  */
 package org.apache.logging.log4j.core.layout;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.InflaterInputStream;
-
+import com.fasterxml.jackson.core.io.JsonStringEncoder;
 import org.apache.commons.io.IOUtils;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.ThreadContext;
@@ -40,12 +34,17 @@ import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.core.util.NetUtils;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
 import org.apache.logging.log4j.util.Chars;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-import com.fasterxml.jackson.core.io.JsonStringEncoder;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
 
 import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -74,7 +73,7 @@ public class GelfLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new)::value);
         ctx.reconfigure();
     }
 
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/HtmlLayoutTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/HtmlLayoutTest.java
index 1ae2921f9a..266ca513d0 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/HtmlLayoutTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/HtmlLayoutTest.java
@@ -32,7 +32,7 @@ import org.apache.logging.log4j.core.time.internal.format.FixedDateFormat;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -87,7 +87,7 @@ public class HtmlLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new)::value);
         ctx.reconfigure();
     }
 
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
index 6346009902..f5211d307f 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
@@ -29,7 +29,7 @@ import org.apache.logging.log4j.core.lookup.MainMapLookup;
 import org.apache.logging.log4j.core.test.BasicConfigurationFactory;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -52,7 +52,7 @@ public class PatternLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new));
         ctx.reconfigure();
     }
 
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/Rfc5424LayoutTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/Rfc5424LayoutTest.java
index 60a6343a14..80bc899987 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/Rfc5424LayoutTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/Rfc5424LayoutTest.java
@@ -16,12 +16,6 @@
  */
 package org.apache.logging.log4j.core.layout;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-import java.util.function.Function;
-
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.ThreadContext;
@@ -47,7 +41,7 @@ import org.apache.logging.log4j.plugins.model.PluginNamespace;
 import org.apache.logging.log4j.plugins.model.PluginType;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
@@ -55,13 +49,14 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.assertj.core.api.Assertions.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.function.Function;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
 
 @UsingAnyThreadContext
 public class Rfc5424LayoutTest {
@@ -92,7 +87,7 @@ public class Rfc5424LayoutTest {
     public static void setupClass() {
         StatusLogger.getLogger().setLevel(Level.OFF);
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new));
         ctx.reconfigure();
     }
 
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java
index 09684b70db..bacc71a710 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java
@@ -28,7 +28,7 @@ import org.apache.logging.log4j.core.test.BasicConfigurationFactory;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
 import org.apache.logging.log4j.message.StructuredDataMessage;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -55,7 +55,7 @@ public class SyslogLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new));
         ctx.reconfigure();
     }
 
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 3521a4abd6..64a4511167 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -60,7 +60,7 @@ import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.model.PluginNamespace;
 import org.apache.logging.log4j.plugins.model.PluginType;
 import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.NameUtil;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.ServiceRegistry;
@@ -308,7 +308,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         if (configSource.getLastModified() > 0) {
             final Source cfgSource = new Source(configSource);
             final Key<WatcherFactory> key = Key.forClass(WatcherFactory.class);
-            injector.registerBindingIfAbsent(key, LazyValue.from(() ->
+            injector.registerBindingIfAbsent(key, Lazy.lazy(() ->
                     new WatcherFactory(injector.getInstance(Watcher.PLUGIN_CATEGORY_KEY))));
             final Watcher watcher = injector.getInstance(key)
                     .newWatcher(cfgSource, this, reconfigurable, listeners, configSource.getLastModified());
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
index bdcad7fb94..531cfd63e6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
@@ -24,7 +24,7 @@ import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.core.util.NetUtils;
 import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.di.Injector;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.LoaderUtil;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.Strings;
@@ -36,7 +36,6 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
-import java.util.function.Supplier;
 
 /**
  * Default factory for using a plugin selected based on the configuration source.
@@ -46,11 +45,11 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
     private static final String ALL_TYPES = "*";
     private static final String OVERRIDE_PARAM = "override";
 
-    private final Supplier<List<ConfigurationFactory>> configurationFactories;
+    private final Lazy<List<ConfigurationFactory>> configurationFactories;
 
     @Inject
     public DefaultConfigurationFactory(final Injector injector) {
-        configurationFactories = new LazyValue<>(() -> loadConfigurationFactories(injector));
+        configurationFactories = Lazy.lazy(() -> loadConfigurationFactories(injector));
     }
 
     /**
@@ -98,7 +97,7 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
                     return getConfiguration(LOG4J1_VERSION, loggerContext, log4j1ConfigStr);
                 }
             }
-            for (final ConfigurationFactory factory : configurationFactories.get()) {
+            for (final ConfigurationFactory factory : configurationFactories.value()) {
                 final String[] types = factory.getSupportedTypes();
                 if (types != null) {
                     for (final String type : types) {
@@ -128,7 +127,7 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
                 return new CompositeConfiguration(configs);
             }
             final String configLocationStr = configLocation.toString();
-            for (final ConfigurationFactory factory : configurationFactories.get()) {
+            for (final ConfigurationFactory factory : configurationFactories.value()) {
                 final String[] types = factory.getSupportedTypes();
                 if (types != null) {
                     for (final String type : types) {
@@ -180,7 +179,7 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
             LOGGER.catching(Level.DEBUG, ex);
         }
         if (source != null) {
-            for (final ConfigurationFactory factory : configurationFactories.get()) {
+            for (final ConfigurationFactory factory : configurationFactories.value()) {
                 if (requiredVersion != null && !factory.getVersion().equals(requiredVersion)) {
                     continue;
                 }
@@ -203,7 +202,7 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
     private Configuration getConfiguration(final LoggerContext loggerContext, final boolean isTest, final String name) {
         final boolean named = Strings.isNotEmpty(name);
         final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
-        for (final ConfigurationFactory factory : configurationFactories.get()) {
+        for (final ConfigurationFactory factory : configurationFactories.value()) {
             String configName;
             final String prefix = isTest ? factory.getTestPrefix() : factory.getDefaultPrefix();
             final String[] types = factory.getSupportedTypes();
@@ -239,7 +238,7 @@ public class DefaultConfigurationFactory extends ConfigurationFactory {
     public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
         if (source != null) {
             final String config = source.getLocation();
-            for (final ConfigurationFactory factory : configurationFactories.get()) {
+            for (final ConfigurationFactory factory : configurationFactories.value()) {
                 final String[] types = factory.getSupportedTypes();
                 if (types != null) {
                     for (final String type : types) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
index 5772b9133c..083b355069 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
@@ -19,12 +19,11 @@ package org.apache.logging.log4j.core.lookup;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 
 import java.lang.management.ManagementFactory;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Supplier;
 
 /**
  * Maps JVM input arguments (but not main arguments) using JMX to acquire JVM arguments.
@@ -36,14 +35,14 @@ import java.util.function.Supplier;
 @Plugin("jvmrunargs")
 public class JmxRuntimeInputArgumentsLookup extends MapLookup {
 
-    private static final Supplier<JmxRuntimeInputArgumentsLookup> INSTANCE = LazyValue.from(() -> {
+    private static final Lazy<JmxRuntimeInputArgumentsLookup> INSTANCE = Lazy.lazy(() -> {
         final List<String> argsList = ManagementFactory.getRuntimeMXBean().getInputArguments();
         return new JmxRuntimeInputArgumentsLookup(MapLookup.toMap(argsList));
     });
 
     @PluginFactory
     public static JmxRuntimeInputArgumentsLookup getInstance() {
-        return INSTANCE.get();
+        return INSTANCE.value();
     }
 
     /**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfigurationFactory.java
index 7c1bf3b583..549d2cfc81 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfigurationFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfigurationFactory.java
@@ -18,11 +18,9 @@ package org.apache.logging.log4j.core.net.ssl;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
-import java.util.function.Supplier;
-
 /**
  * Creates an SSL configuration from Log4j properties.
  */
@@ -44,7 +42,7 @@ public class SslConfigurationFactory {
     private static final String keyStoreKeyManagerFactoryAlgorithm = "log4j2.keyStore.keyManagerFactoryAlgorithm";
     private static final String verifyHostName = "log4j2.ssl.verifyHostName";
 
-    private static final Supplier<SslConfiguration> SSL_CONFIGURATION = LazyValue.from(() -> {
+    private static final Lazy<SslConfiguration> SSL_CONFIGURATION = Lazy.lazy(() -> {
         final PropertiesUtil props = PropertiesUtil.getProperties();
         return createSslConfiguration(props);
     });
@@ -93,6 +91,6 @@ public class SslConfigurationFactory {
     }
 
     public static SslConfiguration getSslConfiguration() {
-        return SSL_CONFIGURATION.get();
+        return SSL_CONFIGURATION.value();
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/BasicContextSelector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/BasicContextSelector.java
index 77fbfb173a..e814928a27 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/BasicContextSelector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/BasicContextSelector.java
@@ -16,10 +16,6 @@
  */
 package org.apache.logging.log4j.core.selector;
 
-import java.net.URI;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.impl.ContextAnchor;
@@ -28,7 +24,11 @@ import org.apache.logging.log4j.plugins.Singleton;
 import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.spi.LoggerContextShutdownAware;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
+
+import java.net.URI;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Returns either this Thread's context or the default LoggerContext.
@@ -38,7 +38,7 @@ public class BasicContextSelector implements ContextSelector, LoggerContextShutd
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
-    protected final LazyValue<LoggerContext> context = LazyValue.from(this::createContext);
+    protected final Lazy<LoggerContext> context = Lazy.lazy(this::createContext);
     protected final Injector injector;
 
     @Inject
@@ -108,7 +108,7 @@ public class BasicContextSelector implements ContextSelector, LoggerContextShutd
 
     @Override
     public List<LoggerContext> getLoggerContexts() {
-        return List.of(context.get());
+        return List.of(context.value());
     }
 
     protected LoggerContext createContext() {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java
index 372a6103ee..c912000892 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.Singleton;
 import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.spi.LoggerContextShutdownAware;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.StackLocatorUtil;
 
 import java.lang.ref.WeakReference;
@@ -53,7 +53,7 @@ public class ClassLoaderContextSelector implements ContextSelector, LoggerContex
 
     protected static final StatusLogger LOGGER = StatusLogger.getLogger();
 
-    protected final LazyValue<LoggerContext> defaultContext = LazyValue.from(() -> createContext(defaultContextName(), null));
+    protected final Lazy<LoggerContext> defaultContext = Lazy.lazy(() -> createContext(defaultContextName(), null));
     protected final Map<String, AtomicReference<WeakReference<LoggerContext>>> contextMap = new ConcurrentHashMap<>();
 
     protected final Injector injector;
@@ -291,7 +291,7 @@ public class ClassLoaderContextSelector implements ContextSelector, LoggerContex
     }
 
     protected LoggerContext getDefault() {
-        return defaultContext.get();
+        return defaultContext.value();
     }
 
     protected String defaultContextName() {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/ClockFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/ClockFactory.java
index 6dbf6835ae..185f27e4e2 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/ClockFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/ClockFactory.java
@@ -21,7 +21,7 @@ import org.apache.logging.log4j.core.time.internal.CoarseCachedClock;
 import org.apache.logging.log4j.core.time.internal.SystemClock;
 import org.apache.logging.log4j.plugins.di.DI;
 import org.apache.logging.log4j.plugins.di.Injector;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 
 /**
  * Factory for {@code Clock} objects.
@@ -35,7 +35,8 @@ public final class ClockFactory {
      * implementation class. The value of this property is {@value}.
      */
     public static final String PROPERTY_NAME = "log4j.Clock";
-    private static final LazyValue<Clock> FALLBACK = new LazyValue<>(() -> {
+    private static final Lazy<Clock> FALLBACK = Lazy.lazy(() -> {
+        // TODO(ms): split out clock bindings for smaller fallback init
         final Injector injector = DI.createInjector();
         injector.init();
         return injector.getInstance(Clock.KEY);
@@ -65,7 +66,7 @@ public final class ClockFactory {
      */
     @Deprecated
     public static Clock getClock() {
-        return FALLBACK.get();
+        return FALLBACK.value();
     }
 
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CachedClock.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CachedClock.java
index e151dcc458..312ec10f98 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CachedClock.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CachedClock.java
@@ -19,10 +19,9 @@ package org.apache.logging.log4j.core.time.internal;
 import org.apache.logging.log4j.core.time.Clock;
 import org.apache.logging.log4j.core.util.Log4jThread;
 import org.apache.logging.log4j.plugins.Factory;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 
 import java.util.concurrent.locks.LockSupport;
-import java.util.function.Supplier;
 
 /**
  * Implementation of the {@code Clock} interface that tracks the time in a
@@ -34,7 +33,7 @@ import java.util.function.Supplier;
  */
 public final class CachedClock implements Clock {
     private static final int UPDATE_THRESHOLD = 1000;
-    private static final Supplier<CachedClock> INSTANCE = new LazyValue<>(CachedClock::new);
+    private static final Lazy<CachedClock> INSTANCE = Lazy.lazy(CachedClock::new);
     private volatile long millis = System.currentTimeMillis();
     private short count = 0;
 
@@ -54,7 +53,7 @@ public final class CachedClock implements Clock {
     @Factory
     public static CachedClock instance() {
         // LOG4J2-819: use lazy initialization of threads
-        return INSTANCE.get();
+        return INSTANCE.value();
     }
 
     /**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CoarseCachedClock.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CoarseCachedClock.java
index 18b9a3e8e2..e8bb95d6b0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CoarseCachedClock.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/time/internal/CoarseCachedClock.java
@@ -18,17 +18,16 @@ package org.apache.logging.log4j.core.time.internal;
 
 import org.apache.logging.log4j.core.time.Clock;
 import org.apache.logging.log4j.core.util.Log4jThread;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 
 import java.util.concurrent.locks.LockSupport;
-import java.util.function.Supplier;
 
 /**
  * This Clock implementation is similar to CachedClock. It is slightly faster at
  * the cost of some accuracy.
  */
 public final class CoarseCachedClock implements Clock {
-    private static final Supplier<CoarseCachedClock> INSTANCE = new LazyValue<>(CoarseCachedClock::new);
+    private static final Lazy<CoarseCachedClock> INSTANCE = Lazy.lazy(CoarseCachedClock::new);
     // ignore IDE complaints; volatile long is fine
     private volatile long millis = System.currentTimeMillis();
 
@@ -55,7 +54,7 @@ public final class CoarseCachedClock implements Clock {
      */
     public static CoarseCachedClock instance() {
         // LOG4J2-819: use lazy initialization of threads
-        return INSTANCE.get();
+        return INSTANCE.value();
     }
 
     /**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java
index 92957ccd69..3815967aeb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java
@@ -16,9 +16,7 @@
  */
 package org.apache.logging.log4j.core.util;
 
-import org.apache.logging.log4j.util.LazyValue;
-
-import java.util.function.Supplier;
+import org.apache.logging.log4j.util.Lazy;
 
 /**
  * This class is borrowed from <a href="https://github.com/FasterXML/jackson-core">Jackson</a>.
@@ -33,7 +31,7 @@ public final class JsonUtils {
      * to use after backslash; and negative values that generic (backslash - u)
      * escaping is to be used.
      */
-    private static final Supplier<int[]> ESC_CODES = LazyValue.from(() -> {
+    private static final Lazy<int[]> ESC_CODES = Lazy.relaxed(() -> {
         final int[] table = new int[128];
         // Control chars need generic escape sequence
         for (int i = 0; i < 32; ++i) {
@@ -77,7 +75,7 @@ public final class JsonUtils {
      */
     public static void quoteAsString(final CharSequence input, final StringBuilder output) {
         final char[] qbuf = getQBuf();
-        final int[] escCodes = ESC_CODES.get();
+        final int[] escCodes = ESC_CODES.value();
         final int escCodeCount = escCodes.length;
         int inPtr = 0;
         final int inputLen = input.length();
diff --git a/log4j-csv/src/test/java/org/apache/logging/log4j/csv/layout/CsvLogEventLayoutTest.java b/log4j-csv/src/test/java/org/apache/logging/log4j/csv/layout/CsvLogEventLayoutTest.java
index 305c4efeb0..ab63cc6e3a 100644
--- a/log4j-csv/src/test/java/org/apache/logging/log4j/csv/layout/CsvLogEventLayoutTest.java
+++ b/log4j-csv/src/test/java/org/apache/logging/log4j/csv/layout/CsvLogEventLayoutTest.java
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.test.BasicConfigurationFactory;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -52,7 +52,7 @@ public class CsvLogEventLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new)::value);
         ctx.reconfigure();
     }
 
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
index 83dba6e2c4..af005df15f 100644
--- a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
@@ -45,7 +45,7 @@ import org.apache.logging.log4j.message.ReusableMessageFactory;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.AbstractLogger;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.SortedArrayStringMap;
 import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.util.Strings;
@@ -89,7 +89,7 @@ public class JsonLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new)::value);
         ctx.reconfigure();
     }
 
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
index 6b29fec8b6..96b1705cf9 100644
--- a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
@@ -41,7 +41,7 @@ import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.AbstractLogger;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -69,7 +69,7 @@ public class XmlLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new));
         ctx.reconfigure();
     }
 
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
index e23db19362..1f16b0b90a 100644
--- a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
@@ -35,7 +35,7 @@ import org.apache.logging.log4j.jackson.yaml.Log4jYamlObjectMapper;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.AbstractLogger;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
@@ -63,7 +63,7 @@ public class YamlLayoutTest {
     @BeforeAll
     public static void setupClass() {
         final LoggerContext ctx = LoggerContext.getContext();
-        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, new LazyValue<>(BasicConfigurationFactory::new));
+        ctx.getInjector().registerBinding(ConfigurationFactory.KEY, Lazy.lazy(BasicConfigurationFactory::new));
         ctx.reconfigure();
     }
 
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
index ce136edf44..480647de8c 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
@@ -17,7 +17,7 @@
 package org.apache.logging.log4j.layout.template.json.util;
 
 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.StringBuilderFormattable;
 import org.apache.logging.log4j.util.StringMap;
 
@@ -28,7 +28,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.BiConsumer;
-import java.util.function.Supplier;
 
 /**
  * A simple JSON writer with support for common Java data types.
@@ -68,7 +67,7 @@ public final class JsonWriter implements AutoCloseable, Cloneable {
      * character to use after backslash; and negative values, that generic
      * (backslash - u) escaping is to be used.
      */
-    private static final Supplier<int[]> ESC_CODES = LazyValue.from(() -> {
+    private static final Lazy<int[]> ESC_CODES = Lazy.relaxed(() -> {
         final int[] table = new int[128];
         // Control chars need generic escape sequence
         for (int i = 0; i < 32; ++i) {
@@ -600,7 +599,7 @@ public final class JsonWriter implements AutoCloseable, Cloneable {
                         : 0;
         final int limit = offset + length + surrogateCorrection;
         int i = offset;
-        final int[] escCodes = ESC_CODES.get();
+        final int[] escCodes = ESC_CODES.value();
         outer:
         while (i < limit) {
             while (true) {
@@ -678,7 +677,7 @@ public final class JsonWriter implements AutoCloseable, Cloneable {
                         : 0;
         final int limit = offset + length + surrogateCorrection;
         int i = offset;
-        final int[] escCodes = ESC_CODES.get();
+        final int[] escCodes = ESC_CODES.value();
         outer:
         while (i < limit) {
             while (true) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index c61f10df99..6d1d28d8f9 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -40,7 +40,7 @@ import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
 import org.apache.logging.log4j.plugins.visit.NodeVisitor;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.EnglishEnums;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.ServiceRegistry;
 import org.apache.logging.log4j.util.StringBuilders;
 
@@ -305,7 +305,7 @@ class DefaultInjector implements Injector {
     }
 
     private Supplier<PluginNamespace> createPluginNamespaceFactory(final Key<PluginNamespace> key) {
-        return LazyValue.from(() -> getInstance(PluginRegistry.class).getNamespace(key.getNamespace(), getPluginPackages()));
+        return Lazy.lazy(() -> getInstance(PluginRegistry.class).getNamespace(key.getNamespace(), getPluginPackages()))::value;
     }
 
     private List<String> getPluginPackages() {
@@ -829,7 +829,7 @@ class DefaultInjector implements Injector {
 
         @Override
         public <T> Supplier<T> get(final Key<T> key, final Supplier<T> unscoped) {
-            return TypeUtil.cast(singletonProviders.computeIfAbsent(key, ignored -> new LazyValue<>(unscoped)));
+            return TypeUtil.cast(singletonProviders.computeIfAbsent(key, ignored -> Lazy.lazy(unscoped)::value));
         }
 
         @Override
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
index f77e82d1d7..0d4a4bbb00 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginRegistry.java
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.plugins.Singleton;
 import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.util.ResolverUtil;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
+import org.apache.logging.log4j.util.Lazy;
 import org.apache.logging.log4j.util.LoaderUtil;
 import org.apache.logging.log4j.util.Strings;
 
@@ -61,7 +61,7 @@ public class PluginRegistry {
     /**
      * Contains plugins found from {@link PluginService} services and legacy Log4j2Plugins.dat cache files in the main CLASSPATH.
      */
-    private final LazyValue<Namespaces> mainPluginNamespaces = LazyValue.from(() -> {
+    private final Lazy<Namespaces> mainPluginNamespaces = Lazy.lazy(() -> {
         final Namespaces namespaces = decodeCacheFiles(LoaderUtil.getClassLoader());
         Throwable throwable = null;
         ClassLoader errorClassLoader = null;
@@ -253,7 +253,7 @@ public class PluginRegistry {
         final var pluginNamespace = new PluginNamespace(namespace);
 
         // First, iterate the PluginService services and legacy Log4j2Plugin.dat files found in the main CLASSPATH
-        final Namespaces builtInPlugins = mainPluginNamespaces.get();
+        final Namespaces builtInPlugins = mainPluginNamespaces.value();
         if (builtInPlugins != null) {
             pluginNamespace.mergeAll(builtInPlugins.get(namespace));
         }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
index 028d56ee77..c210d10713 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/model/PluginType.java
@@ -17,9 +17,7 @@
 package org.apache.logging.log4j.plugins.model;
 
 import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.util.LazyValue;
-
-import java.util.function.Supplier;
+import org.apache.logging.log4j.util.Lazy;
 
 /**
  * Plugin Descriptor. This is a memento object for Plugin annotations paired to their annotated classes.
@@ -30,7 +28,7 @@ import java.util.function.Supplier;
 public class PluginType<T> {
 
     private final PluginEntry pluginEntry;
-    private final Supplier<Class<T>> pluginClass;
+    private final Lazy<Class<T>> pluginClass;
 
     /**
      * Constructor.
@@ -41,7 +39,7 @@ public class PluginType<T> {
     public PluginType(
             final PluginEntry pluginEntry, final Class<T> pluginClass) {
         this.pluginEntry = pluginEntry;
-        this.pluginClass = () -> pluginClass;
+        this.pluginClass = Lazy.value(pluginClass);
     }
 
     /**
@@ -51,7 +49,7 @@ public class PluginType<T> {
      */
     public PluginType(final PluginEntry pluginEntry, final ClassLoader classLoader) {
         this.pluginEntry = pluginEntry;
-        this.pluginClass = LazyValue.from(() -> {
+        this.pluginClass = Lazy.lazy(() -> {
             try {
                 return TypeUtil.cast(classLoader.loadClass(pluginEntry.getClassName()));
             } catch (final ClassNotFoundException e) {
@@ -66,7 +64,7 @@ public class PluginType<T> {
     }
 
     public Class<T> getPluginClass() {
-        return pluginClass.get();
+        return pluginClass.value();
     }
 
     public String getElementType() {
@@ -105,7 +103,7 @@ public class PluginType<T> {
 
     @Override
     public String toString() {
-        return "PluginType [pluginClass=" + pluginClass.get() +
+        return "PluginType [pluginClass=" + pluginClass.toString() +
                 ", key=" + pluginEntry.getKey() +
                 ", elementType=" + pluginEntry.getElementType() +
                 ", isObjectPrintable=" + pluginEntry.isPrintable() +