You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2005/02/06 22:21:58 UTC

svn commit: r151621 - jakarta/commons/proper/logging/trunk/xdocs/guide.xml

Author: rdonkin
Date: Sun Feb  6 13:21:56 2005
New Revision: 151621

URL: http://svn.apache.org/viewcvs?view=rev&rev=151621
Log:
Documentation for improved memory management and optional jar. Contributed by Brian Stansberry. Issue no 31286.

Modified:
    jakarta/commons/proper/logging/trunk/xdocs/guide.xml

Modified: jakarta/commons/proper/logging/trunk/xdocs/guide.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/xdocs/guide.xml?view=diff&r1=151620&r2=151621
==============================================================================
--- jakarta/commons/proper/logging/trunk/xdocs/guide.xml (original)
+++ jakarta/commons/proper/logging/trunk/xdocs/guide.xml Sun Feb  6 13:21:56 2005
@@ -42,6 +42,13 @@
                     </ol>
                 </li>
                 <li><a href='#Developing With JCL'>Developing With JCL</a></li>
+                <li><a href='#Jars Included in the Standard Distribution'>Jars Included in the Standard Distribution</a>
+                     <ol>
+                        <li><a href='#commons-logging.jar'>commons-logging.jar</a></li>
+                        <li><a href='#commons-logging-optional.jar'>commons-logging-optional.jar</a></li>
+                        <li><a href='#commons-logging-api.jar'>commons-logging-api.jar</a></li>
+                     </ol>
+                </li>
                 <li><a href='#JCL Best Practices'>JCL Best Practices</a></li>
                 <li><a href='#Best Practices (General)'>Best Practices (General)</a>
                     <ol>
@@ -55,7 +62,8 @@
                         <li><a href='#Logging Exceptions'>Logging Exceptions</a></li>
                         <li><a href='#When Info Level Instead of Debug?'>When Info Level Instead of Debug?</a></li>
                         <li><a href='#More Control of Enterprise Exception Logging'>More Control of Enterprise Exception Logging</a></li>                    
-                        <li><a href='#National Language Support And Internationalization'>National Language Support And Internationalization</a></li>                    
+                        <li><a href='#National Language Support And Internationalization'>National Language Support And Internationalization</a></li>
+                        <li><a href='#Classloader and Memory Management'>Classloader and Memory Management</a></li>
                     </ol>
                 </li>
                 <li><a href='#Extending Commons Logging'>Extending Commons Logging</a>
@@ -300,6 +308,61 @@
         </source>
     </ul>
 </section>
+<section name="Jars Included in the Standard Distribution">
+    <subsection name="commons-logging.jar">
+      <p>
+The <code>commons-logging.jar</code> file includes the JCL API, the default 
+<code>LogFactory</code> implemenation and thin-wrapper <code>Log</code> 
+implementations for
+<a href="http://jakarta.apache.org/log4j/docs/index.html">Log4J</a>,
+<a href="http://jakarta.apache.org/avalon/logkit/index.html">Avalon LogKit</a>,
+the Avalon Framework's logging infrastructure,
+JDK 1.4, as well as an implementation of JDK 1.4 logging APIs (JSR-47) for 
+pre-1.4 systems.
+   </p>
+   <p>
+In most cases, including <code>commons-logging.jar</code> and your preferred 
+logging implementation in the classpath should be all that is required to 
+use JCL.
+   </p>
+    </subsection>
+    <subsection name="commons-logging-optional.jar">
+    <p>
+The optional jar includes, oddly enough, optional classes that are useful but 
+not strictly required to make JCL functional.  As these classes introduce 
+dependencies on JDK 1.3+ JVMs and a goal of JCL is to be usable on JDK 1.2 
+and earlier JVMs, these optional classes are not included in the main 
+<code>commons-logging.jar</code>.
+   </p>
+   <p>
+Included in the optional jar are classes which allow JCL to (potentially) improve
+it's memory utilization (see 
+<a href='#Classloader and Memory Management'>Classloader and Memory Management</a> 
+below). It is therefore recommended that (when running on a 1.3+ JDK) the optional jar 
+be deployed alongside the 
+main <code>commons-logging.jar</code>.  It should be deployed such that it will be loaded 
+by the same classloader that loads <code>LogFactory</code>. When so deployed, JCL will
+discover the appropriate classes and configure itself to use them.
+   </p>
+    </subsection>
+    <subsection name="commons-logging-api.jar">
+    <p>
+The <code>commons-logging-api.jar</code> file includes the JCL API and the 
+default <code>LogFactory</code> implementation, but does not include the 
+wrapper <code>Log</code> implementations for <code>Log4j</code>,
+<code>Avalon</code> and <code>Lumberjack</code>.  This jar is intended for 
+use in specialized containers such as 
+<a href='http://jakarta.apache.org/tomcat'>Tomcat</a> that wish to use 
+JCL internally but also need to make JCL available for use by deployed 
+applications.
+   </p>
+  <p>
+  If this jar is used, in order to benefit from improved memory management in modern JVMs (1.3+),
+  it is recommended that the <code>commons-logging-optional.jar</code> is deployed in 
+  the same classloader as this jar.
+  </p>
+    </subsection>
+</section>
         <section name='JCL Best Practices'>
             <p>
 Best practices for JCL are presented in two categories:
@@ -500,6 +563,77 @@
 Perhaps more direct support for internationalizing log messages
 can be introduced in a future or alternate version of the <code>Log</code> interface.
                 </p>
+            </subsection>
+            <subsection name="Classloader and Memory Management">
+            <p>
+The <code>LogFactory</code> discovery process (see 
+<a href='#Configuration'>Configuration</a> above) is a fairly expensive 
+operation, so JCL certainly should not perform it each time user code 
+invokes: 
+</p>
+<source>LogFactory.getLog()</source> 
+<p>
+Instead JCL caches the 
+<code>LogFactory</code> implementation created as a result of the discovery 
+process and uses the cached factory to return <code>Log</code> objects.  
+Since in J2EE and similar multi-classloader environments, the result of the 
+discovery process can vary depending on the thread context classloader 
+(e.g. one webapp in a web container may be configured to use Log4j and 
+another to use JDK 1.4 logging), JCL internally caches the 
+<code>LogFactory</code> instances in a static hashtable, keyed by classloader.
+            </p>
+            <p>
+While this approach is efficient, it can lead to memory leaks if container
+implementors are not careful to call 
+</p>
+<source>LogFactory.release()</source> 
+<p>
+whenever a classloader that has utilized JCL is undeployed.  If 
+<code>release()</code> is not called, a reference to the undeployed 
+classloader (and thus to all the classes loaded by it) will be
+held in <code>LogFactory</code>'s static hashtable.
+            </p>
+            <p>
+Beginning with JCL 1.0.5, <code>LogFactory</code> will attempt to cache factory
+implementations in a 
+<a href='http://jakarta.apache.org/commons/logging/api/org/apache/commons/logging/impl/WeakHashtable.java'>WeakHashtable</a>.  
+This class is analogous to <code>java.util.WeakHashMap</code> in that it holds 
+<code>WeakReference</code>s to its keys, thus allowing classloaders to be GC'd 
+even if <code>LogFactory.release()</code> is never invoked.
+            </p>
+            <p>
+Because <code>WeakHashtable</code> depends on JDK 1.3+ features, it cannot 
+be included in the main <code>commons-logging.jar</code> file.  It is found 
+in <code>commons-logging-optional.jar</code>.  <strong>J2EE container 
+implementors who distribute JCL with their application are strongly 
+encouraged to place <code>commons-logging-optional.jar</code> on the classpath 
+in the same location where <code>LogFactory</code> is loaded.</strong>
+            </p>
+            <p>
+In a particular usage scenario, <code>WeakHashtable</code> alone will
+be insufficent to allow garbage collection of a classloader without a call to
+<code>release</code>.  If the abstract class <code>LogFactory</code> is 
+loaded by a parent classloader and a concrete subclass implementation of 
+<code>LogFactory</code> is loaded by a child classloader, the concrete
+implementation will have a strong reference to the child classloader via the
+chain <code>getClass().getClassLoader()</code>. The <code>WeakHashtable</code>
+will have a strong reference to the <code>LogFactory</code> implementation as
+one of the values in its map. This chain of references will prevent 
+collection of the child classloader.
+           </p>
+           <p>
+Such a situation would typically only occur if commons-logging.jar were
+loaded by a parent classloader (e.g. a server level classloader in a
+servlet container) and a custom <code>LogFactory</code> implementation were
+loaded by a child classloader (e.g. a web app classloader).  If use of
+a custom <code>LogFactory</code> subclass is desired, ensuring that the
+custom subclass is loaded by the same classloader as <code>LogFactory</code>
+will prevent problems.  In normal deployments, the standard implementations 
+of <code>LogFactory</code> found in package <code>org.apache.commons.logging.impl</code> 
+will be loaded by the same classloader that loads <code>LogFactory</code> 
+itself, so use of the standard <code>LogFactory</code> implementation
+should not pose problems.
+         </p>
             </subsection>
     </section>
     <section name='Extending Commons Logging'>



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org