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