Author: grobmeier
Date: Mon Apr 30 16:14:02 2012
New Revision: 1332275
URL: http://svn.apache.org/viewvc?rev=1332275&view=rev
Log:
applied one more mdc fix from Maarten Bosteels. Thanks!
Added:
logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java
(with props)
Modified:
logging/log4j/trunk/src/main/java/org/apache/log4j/MDC.java
Modified: logging/log4j/trunk/src/main/java/org/apache/log4j/MDC.java
URL:
http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/MDC.java?rev=1332275&r1=1332274&r2=1332275&view=diff
==============================================================================
--- logging/log4j/trunk/src/main/java/org/apache/log4j/MDC.java (original)
+++ logging/log4j/trunk/src/main/java/org/apache/log4j/MDC.java Mon Apr 30
16:14:02 2012
@@ -41,7 +41,8 @@ import org.apache.log4j.helpers.ThreadLo
@since 1.2
- @author Ceki Gülcü */
+ @author Ceki Gülcü
+*/
public class MDC {
final static MDC mdc = new MDC();
@@ -53,7 +54,7 @@ public class MDC {
Object tlm;
private Method removeMethod;
-
+
private
MDC() {
java1 = Loader.isJava1();
@@ -170,6 +171,10 @@ public class MDC {
Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
if(ht != null) {
ht.remove(key);
+ // clean up if this was the last key
+ if (ht.isEmpty()) {
+ clear0();
+ }
}
}
}
Added: logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java
URL:
http://svn.apache.org/viewvc/logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java?rev=1332275&view=auto
==============================================================================
--- logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java (added)
+++ logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java Mon
Apr 30 16:14:02 2012
@@ -0,0 +1,98 @@
+/*
+ * 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.log4j;
+
+import java.lang.ref.Reference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import junit.framework.TestCase;
+
+/**
+ * Test for MDC
+ *
+ * @author Maarten Bosteels
+ */
+public class MDCTestCase extends TestCase {
+
+ public void setUp() {
+ MDC.clear();
+ }
+
+ public void tearDown() {
+ MDC.clear();
+ }
+
+ public void testPut() throws Exception {
+ MDC.put("key", "some value");
+ assertEquals("some value", MDC.get("key"));
+ assertEquals(1, MDC.getContext().size());
+ }
+
+ public void testRemoveLastKey() throws Exception {
+ MDC.put("key", "some value");
+
+ MDC.remove("key");
+ checkThreadLocalsForLeaks();
+ }
+
+ private void checkThreadLocalsForLeaks() throws Exception {
+
+ // this code is heavily based on code in
org.apache.catalina.loader.WebappClassLoader
+
+ // Make the fields in the Thread class that store ThreadLocals
accessible
+ Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
+ threadLocalsField.setAccessible(true);
+ Field inheritableThreadLocalsField =
Thread.class.getDeclaredField("inheritableThreadLocals");
+ inheritableThreadLocalsField.setAccessible(true);
+ // Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects
accessible
+ Class tlmClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
+ Field tableField = tlmClass.getDeclaredField("table");
+ tableField.setAccessible(true);
+
+ Thread thread = Thread.currentThread();
+
+ Object threadLocalMap;
+ threadLocalMap = threadLocalsField.get(thread);
+ // Check the first map
+ checkThreadLocalMapForLeaks(threadLocalMap, tableField);
+ // Check the second map
+ threadLocalMap = inheritableThreadLocalsField.get(thread);
+ checkThreadLocalMapForLeaks(threadLocalMap, tableField);
+
+ }
+
+ private void checkThreadLocalMapForLeaks(Object map, Field
internalTableField)
+ throws IllegalAccessException, NoSuchFieldException {
+ if (map != null) {
+ Object[] table = (Object[]) internalTableField.get(map);
+ if (table != null) {
+ for (int j =0; j < table.length; j++) {
+ if (table[j] != null) {
+
+ // Check the key
+ Object key = ((Reference) table[j]).get();
+ String keyClassName = key.getClass().getName();
+
+ if (key.getClass() ==
org.apache.log4j.helpers.ThreadLocalMap.class) {
+ fail("Found a ThreadLocal with key of type [" + keyClassName +
"]");
+ }
+ }
+ }
+ }
+ }
+ }
+}
Propchange: logging/log4j/trunk/tests/src/java/org/apache/log4j/MDCTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native