You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2019/12/31 23:38:53 UTC
[logging-log4j2] branch master updated: LOG4J2-2754:
LoaderUtil.getClassLoaders may discover additional loaders
This is an automated email from the ASF dual-hosted git repository.
ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new 0db2bbb LOG4J2-2754: LoaderUtil.getClassLoaders may discover additional loaders
0db2bbb is described below
commit 0db2bbb948dd7e13749efa2b47891678b71f25d3
Author: Carter Kozak <ck...@ckozak.net>
AuthorDate: Tue Dec 31 15:10:15 2019 -0500
LOG4J2-2754: LoaderUtil.getClassLoaders may discover additional loaders
The utility no longer erroneously returns a result with a null element in some
environments.
Also updated loadClass to avoid internally throwing and catching a null
pointer exception when getThreadContextClassLoader returns null.
---
.../org/apache/logging/log4j/util/LoaderUtil.java | 50 +++++++++++-----------
src/changes/changes.xml | 3 ++
2 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
index 845b1e0..3eccabd 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
@@ -21,11 +21,9 @@ import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;
-import java.util.List;
import java.util.Objects;
/**
@@ -149,26 +147,16 @@ public final class LoaderUtil {
}
public static ClassLoader[] getClassLoaders() {
- List<ClassLoader> classLoaders = new ArrayList<>();
- ClassLoader tcl = getThreadContextClassLoader();
- classLoaders.add(tcl);
- if (!isForceTccl()) {
- // Some implementations may use null to represent the bootstrap class loader.
- ClassLoader current = LoaderUtil.class.getClassLoader();
- if (current != null && current != tcl) {
- classLoaders.add(current);
- ClassLoader parent = current.getParent();
- while (parent != null && !classLoaders.contains(parent)) {
- classLoaders.add(parent);
- }
- }
- ClassLoader parent = tcl == null ? null : tcl.getParent();
- while (parent != null && !classLoaders.contains(parent)) {
- classLoaders.add(parent);
- parent = parent.getParent();
- }
- ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
- if (!classLoaders.contains(systemClassLoader)) {
+ final Collection<ClassLoader> classLoaders = new LinkedHashSet<>();
+ final ClassLoader tcl = getThreadContextClassLoader();
+ if (tcl != null) {
+ classLoaders.add(tcl);
+ }
+ if (!isForceTccl()) {
+ accumulateClassLoaders(LoaderUtil.class.getClassLoader(), classLoaders);
+ accumulateClassLoaders(tcl == null ? null : tcl.getParent(), classLoaders);
+ final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ if (systemClassLoader != null) {
classLoaders.add(systemClassLoader);
}
}
@@ -176,6 +164,17 @@ public final class LoaderUtil {
}
/**
+ * Adds the provided loader to the loaders collection, and traverses up the tree until either a null
+ * value or a classloader which has already been added is encountered.
+ */
+ private static void accumulateClassLoaders(ClassLoader loader, Collection<ClassLoader> loaders) {
+ // Some implementations may use null to represent the bootstrap class loader.
+ if (loader != null && loaders.add(loader)) {
+ accumulateClassLoaders(loader.getParent(), loaders);
+ }
+ }
+
+ /**
* Determines if a named Class can be loaded or not.
*
* @param className The class name.
@@ -208,10 +207,13 @@ public final class LoaderUtil {
return Class.forName(className);
}
try {
- return getThreadContextClassLoader().loadClass(className);
+ ClassLoader tccl = getThreadContextClassLoader();
+ if (tccl != null) {
+ return tccl.loadClass(className);
+ }
} catch (final Throwable ignored) {
- return Class.forName(className);
}
+ return Class.forName(className);
}
/**
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3bc396f..d1175e1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -196,6 +196,9 @@
<action issue="LOG4J2-2752" dev="ckozak" type="fix">
MutableLogEvent and RingBufferLogEvent avoid StringBuffer and parameter array allocation unless reusable messages are used.
</action>
+ <action issue="LOG4J2-2754" dev="ckozak" type="fix">
+ LoaderUtil.getClassLoaders may discover additional loaders and no longer erroneously returns a result with a null element in some environments.
+ </action>
</release>
<release version="2.13.0" date="2019-12-11" description="GA Release 2.13.0">
<action issue="LOG4J2-2058" dev="rgoers" type="fix">