LOG4J2-1417 added internal representation that does not store non-JDK classes 
in ThreadLocals for safe use in web applications


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/83b930dc
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/83b930dc
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/83b930dc

Branch: refs/heads/master
Commit: 83b930dcf07fe68a8220c452a34cb2385525096b
Parents: cff46e4
Author: rpopma <[email protected]>
Authored: Sat Jun 11 17:20:51 2016 +0900
Committer: rpopma <[email protected]>
Committed: Sat Jun 11 17:20:51 2016 +0900

----------------------------------------------------------------------
 .../org/apache/logging/log4j/util/Unbox.java    | 46 +++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/83b930dc/log4j-api/src/main/java/org/apache/logging/log4j/util/Unbox.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Unbox.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/Unbox.java
index 137a702..d0bb16f 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Unbox.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Unbox.java
@@ -52,6 +52,49 @@ public class Unbox {
     private static final int RINGBUFFER_SIZE = 
calculateRingBufferSize("log4j.unbox.ringbuffer.size");
     private static final int MASK = RINGBUFFER_SIZE - 1;
 
+    /**
+     * State implementation that only puts JDK classes in ThreadLocals, so 
this is safe to be used from
+     * web applications. Web application containers have thread pools that may 
hold on to ThreadLocal objects
+     * after the application was stopped. This may prevent the classes of the 
application from being unloaded,
+     * causing memory leaks.
+     * <p>
+     * Such memory leaks will not occur if only JDK classes are stored in 
ThreadLocals.
+     * </p>
+     */
+    private static class WebSafeState {
+        private final ThreadLocal<StringBuilder[]> ringBuffer = new 
ThreadLocal<>();
+        private final ThreadLocal<int[]> current = new ThreadLocal<>();
+
+        public StringBuilder getStringBuilder() {
+            StringBuilder[] array = ringBuffer.get();
+            if (array == null) {
+                array = new StringBuilder[RINGBUFFER_SIZE];
+                for (int i = 0; i < array.length; i++) {
+                    array[i] = new StringBuilder(21);
+                }
+                ringBuffer.set(array);
+                current.set(new int[1]);
+            }
+            int[] index = current.get();
+            final StringBuilder result = array[MASK & index[0]++];
+            result.setLength(0);
+            return result;
+        }
+
+        public boolean isBoxedPrimitive(final StringBuilder text) {
+            StringBuilder[] array = ringBuffer.get();
+            if (array == null) {
+                return false;
+            }
+            for (int i = 0; i < array.length; i++) {
+                if (text == array[i]) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     private static class State {
         private final StringBuilder[] ringBuffer = new 
StringBuilder[RINGBUFFER_SIZE];
         private int current;
@@ -77,6 +120,7 @@ public class Unbox {
         }
     }
     private static ThreadLocal<State> threadLocalState = new ThreadLocal<>();
+    private static WebSafeState webSafeState = new WebSafeState();
 
     private Unbox() {
         // this is a utility
@@ -218,7 +262,7 @@ public class Unbox {
     }
 
     private static StringBuilder getSB() {
-        return getState().getStringBuilder();
+        return Constants.ENABLE_THREADLOCALS ? getState().getStringBuilder() : 
webSafeState.getStringBuilder();
     }
 
     /** For testing. */

Reply via email to