View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.logging;
19  
20  import java.lang.ref.WeakReference;
21  import java.lang.reflect.Field;
22  
23  import junit.framework.TestCase;
24  
25  public class LogFactoryWeakReferenceTestCase extends TestCase {
26      private static final long MAX_WAIT_FOR_REF_NULLED_BY_GC = 15_000;
27  
28      public void testNotLeakingThisClassLoader() throws Exception {
29          // create an isolated loader
30          PathableClassLoader loader = new PathableClassLoader(null);
31          loader.addLogicalLib("commons-logging");
32  
33          // load the LogFactory class through this loader
34          Class<?> logFactoryClass = loader.loadClass(LogFactory.class.getName());
35  
36          // reflection hacks to obtain the weak reference
37          Field field = logFactoryClass.getDeclaredField("thisClassLoaderRef");
38          field.setAccessible(true);
39          final WeakReference thisClassLoaderRef = (WeakReference) field.get(null);
40  
41          // the ref should at this point contain the loader
42          assertSame(loader, thisClassLoaderRef.get());
43  
44          // null out the hard refs
45          field = null;
46          logFactoryClass = null;
47          loader.close();
48          loader = null;
49  
50          final GarbageCollectionHelper gcHelper = new GarbageCollectionHelper();
51          gcHelper.run();
52          try {
53              final long start = System.currentTimeMillis();
54              while (thisClassLoaderRef.get() != null) {
55                  if (System.currentTimeMillis() - start > MAX_WAIT_FOR_REF_NULLED_BY_GC) {
56                      fail("After waiting " + MAX_WAIT_FOR_REF_NULLED_BY_GC + "ms, the weak ref still yields a non-null value.");
57                  }
58                  Thread.sleep(100);
59              }
60          } finally {
61              gcHelper.close();
62          }
63      }
64  }