diff --git a/xdocs/guide.xml b/xdocs/guide.xml index b17d7ae..3e2936c 100644 --- a/xdocs/guide.xml +++ b/xdocs/guide.xml @@ -42,6 +42,13 @@
  • Developing With JCL
  • +
  • Jars Included in the Standard Distribution +
      +
    1. commons-logging.jar
    2. +
    3. commons-logging-optional.jar
    4. +
    5. commons-logging-api.jar
    6. +
    +
  • JCL Best Practices
  • Best Practices (General)
      @@ -55,7 +62,8 @@
    1. Logging Exceptions
    2. When Info Level Instead of Debug?
    3. More Control of Enterprise Exception Logging
    4. -
    5. National Language Support And Internationalization
    6. +
    7. National Language Support And Internationalization
    8. +
    9. Classloader and Memory Management
  • Extending Commons Logging @@ -299,6 +307,61 @@ In addition to the logging methods, the following are provided for code guards: log.isTraceEnabled(); + +
    + +

    +The commons-logging.jar file includes the JCL API, the default +LogFactory implemenation and thin-wrapper Log +implementations for +Log4J, +Avalon LogKit, +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. +

    +

    +In most cases, including commons-logging.jar and your preferred +logging implementation in the classpath should be all that is required to +use JCL. +

    +
    + +

    +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 +commons-logging.jar. +

    +

    +Included in the optional jar are classes which allow JCL to (potentially) improve +it's memory utilization (see +Classloader and Memory Management +below). It is therefore recommended that (when running on a 1.3+ JDK) the optional jar +be deployed alongside the +main commons-logging.jar. It should be deployed such that it will be loaded +by the same classloader that loads LogFactory. When so deployed, JCL will +discover the appropriate classes and configure itself to use them. +

    +
    + +

    +The commons-logging-api.jar file includes the JCL API and the +default LogFactory implementation, but does not include the +wrapper Log implementations for Log4j, +Avalon and Lumberjack. This jar is intended for +use in specialized containers such as +Tomcat that wish to use +JCL internally but also need to make JCL available for use by deployed +applications. +

    +

    + If this jar is used, in order to benefit from improved memory management in modern JVMs (1.3+), + it is recommended that the commons-logging-optional.jar is deployed in + the same classloader as this jar. +

    +

    @@ -501,6 +564,77 @@ Perhaps more direct support for internationalizing log messages can be introduced in a future or alternate version of the Log interface.

    + +

    +The LogFactory discovery process (see +Configuration above) is a fairly expensive +operation, so JCL certainly should not perform it each time user code +invokes: +

    +LogFactory.getLog() +

    +Instead JCL caches the +LogFactory implementation created as a result of the discovery +process and uses the cached factory to return Log 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 +LogFactory instances in a static hashtable, keyed by classloader. +

    +

    +While this approach is efficient, it can lead to memory leaks if container +implementors are not careful to call +

    +LogFactory.release() +

    +whenever a classloader that has utilized JCL is undeployed. If +release() is not called, a reference to the undeployed +classloader (and thus to all the classes loaded by it) will be +held in LogFactory's static hashtable. +

    +

    +Beginning with JCL 1.0.5, LogFactory will attempt to cache factory +implementations in a +WeakHashtable. +This class is analogous to java.util.WeakHashMap in that it holds +WeakReferences to its keys, thus allowing classloaders to be GC'd +even if LogFactory.release() is never invoked. +

    +

    +Because WeakHashtable depends on JDK 1.3+ features, it cannot +be included in the main commons-logging.jar file. It is found +in commons-logging-optional.jar. J2EE container +implementors who distribute JCL with their application are strongly +encouraged to place commons-logging-optional.jar on the classpath +in the same location where LogFactory is loaded. +

    +

    +In a particular usage scenario, WeakHashtable alone will +be insufficent to allow garbage collection of a classloader without a call to +release. If the abstract class LogFactory is +loaded by a parent classloader and a concrete subclass implementation of +LogFactory is loaded by a child classloader, the concrete +implementation will have a strong reference to the child classloader via the +chain getClass().getClassLoader(). The WeakHashtable +will have a strong reference to the LogFactory implementation as +one of the values in its map. This chain of references will prevent +collection of the child classloader. +

    +

    +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 LogFactory implementation were +loaded by a child classloader (e.g. a web app classloader). If use of +a custom LogFactory subclass is desired, ensuring that the +custom subclass is loaded by the same classloader as LogFactory +will prevent problems. In normal deployments, the standard implementations +of LogFactory found in package org.apache.commons.logging.impl +will be loaded by the same classloader that loads LogFactory +itself, so use of the standard LogFactory implementation +should not pose problems. +

    +