| <?xml version="1.0"?> |
| |
| <!-- |
| |
| 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. |
| |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Troubleshooting Guide</title> |
| <author email="dev@commons.apache.org">Commons Documentation Team</author> |
| </properties> |
| |
| <body> |
| <section name="Contents"> |
| <ul> |
| <li> |
| <a href="#Contents">Contents</a> |
| </li> |
| <li> |
| <a href="#Using JCL Diagnostics">Using JCL Diagnostics</a> |
| <ul> |
| <li> |
| <a href="#When To Use Diagnostic Logging">When To Use Diagnostic Logging</a> |
| <ul/> |
| </li> |
| <li> |
| <a href="#How To Use Diagnostic logging">How To Use Diagnostic logging</a> |
| </li> |
| <li> |
| <a href="#OIDs">OIDs</a> |
| </li> |
| <li> |
| <a href="#Diagnostic Message Prefix">Diagnostic Message Prefix</a> |
| </li> |
| <li> |
| <a href="#ClassLoader Hierarchy Tree">ClassLoader Hierarchy Tree</a> |
| </li> |
| <li> |
| <a href="#LogFactory Class Bootstrap">LogFactory Class Bootstrap</a> |
| </li> |
| <li> |
| <a href="#Construction Of LogFactoryImpl Instances">Construction Of LogFactoryImpl Instances</a> |
| </li> |
| <li> |
| <a href="#Log Discovery Diagnostics">Log Discovery Diagnostics</a> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <a href="#Containers With Custom LogFactory Implementations">Containers With Custom LogFactory Implementations</a> |
| <ul> |
| <li> |
| <a href="#The Incompatible LogFactory Issue">The Incompatible LogFactory Issue</a> |
| <ul> |
| <li> |
| <a href="#Symptoms">Symptoms</a> |
| </li> |
| <li> |
| <a href="#Explanation">Explanation</a> |
| </li> |
| <li> |
| <a href="#Fixes">Fixes</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <a href="#Containers With Custom ClassLoading Behaviour for Logging">Containers With Custom ClassLoading Behaviour for Logging</a> |
| <ul> |
| <li> |
| <a href="#Apache Tomcat">Apache Tomcat</a> |
| <ul/> |
| </li> |
| <li> |
| <a href="#JBoss Application Server">JBoss Application Server</a> |
| <ul/> |
| </li> |
| <li> |
| <a href="#Other Containers">Other Containers</a> |
| <ul/> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </section> |
| <section name='Using JCL Diagnostics'> |
| <p> |
| Diagnostics is a feature introduced in JCL 1.1 as an aid to debugging problems |
| with JCL configurations. When diagnostics are switched on, messages are logged |
| to a stream (specified by the user) by the two main classes involved in discovery |
| in JCL (<code>LogFactory</code> and <code>LogFactoryImpl</code>). |
| </p> |
| <p> |
| Diagnostics are intended to be used in conjunction with the source. The source |
| contains numerous and lengthy comments. Often these are intended to help explain |
| the meaning of the messages. |
| </p> |
| <subsection name='When To Use Diagnostic Logging'> |
| <p> |
| Diagnostic logging is intended only to be used when debugging a problematic |
| configuration. It <em>should</em> be switched off for production. |
| </p> |
| </subsection> |
| <subsection name='How To Use Diagnostic logging'> |
| <p> |
| Diagnostic logging is controlled through the system property |
| <code>org.apache.commons.logging.diagnostics.dest</code>. Setting the property value |
| to the special strings <code>STDOUT</code> or <code>STDERR</code> (case-sensitive) |
| will output messages to <code>System.out</code> and <code>System.err</code> respectively. |
| Setting the property value to a valid file name will result in the messages being logged |
| to that file. |
| </p> |
| </subsection> |
| <subsection name='OIDs'> |
| <p> |
| Diagnostics uses the concept of an Object ID (OID). This allows the identity of objects |
| to be tracked without relying on useful <code>toString</code> implementations. |
| These are of the form: |
| </p> |
| <code><pre> |
| <em>classname</em>@<em>system identity hash code</em> |
| </pre></code> |
| <p> |
| The <em>system identity hash code</em> is found by calling <code>System.identityHashCode()</code> |
| which should uniquely identify a particular instance. The classname is usually the fully qualified |
| class name though in a few cases, <code>org.apache.commons.logging.impl.LogFactoryImpl</code> may be |
| shortened to <code>LogFactoryImpl</code> to increase ease of reading. For example: |
| </p> |
| <code><pre> |
| sun.misc.Launcher$AppClassLoader@20120943 |
| LogFactoryImpl@1671711 |
| </pre></code> |
| <p> |
| OIDs are intended to be used to cross-reference. They allow particular instances of classloaders |
| and JCL classes to be tracked in different contexts. This plays a vital role in building |
| up the understanding of the classloader environment required to diagnose JCL problems. |
| </p> |
| </subsection> |
| <subsection name='Diagnostic Message Prefix'> |
| <p> |
| Each diagnostic message is prefixed with details of the relevant class in a standard format. |
| This takes the form: |
| </p> |
| <code><pre> |
| [<em>class-identifier</em> from <em>ClassLoader OID</em>] |
| </pre></code> |
| <p> |
| <em>ClassLoader OID</em> is the <a href='#OIDs'>OID</a> of a classloader which loaded |
| the class issuing the message. |
| <em>class-identifier</em> identifies the object issuing the message. |
| </p> |
| <p> |
| In the case of |
| <code>LogFactory</code>, this is just <code>LogFactory</code>. For example (line split): |
| </p> |
| <code><pre> |
| [LogFactory |
| from sun.misc.Launcher$AppClassLoader@20120943] BOOTSTRAP COMPLETED |
| </pre></code> |
| <p> |
| In the case of |
| <code>LogFactoryImpl</code>, the prefix is the instance OID. This can be cross referenced |
| to discover the details of the TCCL used to manage this instance. For example (line split): |
| </p> |
| <code><pre> |
| [LogFactoryImpl@1671711 |
| from sun.misc.Launcher$AppClassLoader@20120943] Instance created. |
| </pre></code> |
| </subsection> |
| <subsection name='ClassLoader Hierarchy Tree'> |
| <p> |
| Understanding the relationships between classloaders is vital when debugging JCL. |
| At various points, JCL will print to the diagnostic log the hierarchy for important |
| classloaders. This is obtained by walking the tree using <code>getParent</code>. |
| Each classloader is represented (visually) by an OID (to allow cross referencing) |
| and the relationship indicated in <code><em>child</em> --> <em>parent</em></code> fashion. |
| For example (line split for easy reading): |
| </p> |
| <code><pre> |
| ClassLoader tree:java.net.URLClassLoader@3526198 |
| --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM) |
| --> sun.misc.Launcher$ExtClassLoader@11126876 |
| --> BOOT |
| </pre></code> |
| <p> |
| Represents a hierarchy with four elements ending in the boot classloader. |
| </p> |
| </subsection> |
| <subsection name='LogFactory Class Bootstrap'> |
| <p> |
| Whenever the <code>LogFactory</code> class is initialized, diagnostic messages about |
| the classloader environment are logged. The content of each of these messages is prefixed by |
| <code>[ENV]</code> to help distinguish them. The extension directories, application classpath, |
| details of the classloader (including the <a href='#OIDs'>OID</a> and <code>toString</code> |
| value) used to load <code>LogFactory</code> and the |
| <a href='#ClassLoader%20Hierarchy%20Tree'>classloader tree</a> for that classloader |
| are logged. |
| </p> |
| <p> |
| Many Sun classloaders have confusing <code>toString</code> values. For example, the OID may be |
| </p> |
| <code><pre> |
| sun.misc.Launcher$AppClassLoader@20120943 |
| </pre></code> |
| <p> |
| with a <code>toString</code> value of |
| </p> |
| <code><pre> |
| sun.misc.Launcher$AppClassLoader@133056f |
| </pre></code> |
| <p> |
| Other classloader implementations may give very useful information (such as the local classpath). |
| </p> |
| <p> |
| Finally, once initialization is complete a <code>BOOTSTRAP COMPLETED</code> message is issued. |
| </p> |
| </subsection> |
| <subsection name='Construction Of LogFactoryImpl Instances'> |
| <p> |
| <code>LogFactoryImpl</code> is the standard and default <code>LogFactory</code> implementation. |
| This section obviously only applies to configurations using this implementation. |
| </p> |
| <p> |
| Before assigning a <code>Log</code> instance, <code>LogFactory</code> loads a |
| <code>LogFactory</code> implementation. The content is prefixed by <code>[LOOKUP]</code> |
| for each diagnostic message logged by this process. |
| </p> |
| <p> |
| The implementation used can vary per Thread context classloader (TCCL). If this is the first time |
| that a Log has been requested for a particular TCCL a new instance will be created. |
| </p> |
| <p> |
| Information of particular interest is logged at this stage. Details of the TCCL are logged |
| allowing the <a href='#OIDs'>OID</a> later to be cross-referenced to the <code>toString</code> value |
| and the <a href='#ClassLoader%20Hierarchy%20Tree'>classloader tree</a>. For example, the |
| following log snippet details the TCCL (lines split): |
| </p> |
| <code><pre> |
| [LogFactory from sun.misc.Launcher$AppClassLoader@20120943] |
| [LOOKUP] LogFactory implementation requested for the first time for context |
| classloader java.net.URLClassLoader@3526198 |
| [LogFactory from sun.misc.Launcher$AppClassLoader@20120943] |
| [LOOKUP] java.net.URLClassLoader@3526198 == 'java.net.URLClassLoader@35ce36' |
| [LogFactory from sun.misc.Launcher$AppClassLoader@20120943] |
| [LOOKUP] ClassLoader tree:java.net.URLClassLoader@3526198 |
| --> sun.misc.Launcher$AppClassLoader@20120943 (SYSTEM) |
| --> sun.misc.Launcher$ExtClassLoader@11126876 |
| --> BOOT |
| </pre></code> |
| </subsection> |
| <subsection name='Log Discovery Diagnostics'> |
| <p> |
| The standard <code>LogFactoryImpl</code> issues many diagnostic messages when discovering |
| the <code>Log</code> implementation to be used. |
| </p> |
| <p> |
| During discovery, environment variables are loaded and values set. This content is prefixed by |
| <code>[ENV]</code> to make it easier to distinguish this material. |
| </p> |
| <p> |
| The possible messages issued during discovery are numerous. To understand them, the source |
| should be consulted. Attention should be paid to the classloader hierarchy trees for the |
| classloader used to load <code>LogFactory</code> and to the TCCL. |
| </p> |
| </subsection> |
| </section> |
| <section name='Containers With Custom LogFactory Implementations'> |
| <p> |
| Some containers use a custom <code>LogFactory</code> implementation to adapt JCL to their particular |
| logging system. This has some important consequences for the deployment of applications using JCL within |
| these containers. |
| </p> |
| <p> |
| Containers known to use this mechanism: |
| </p> |
| <ul> |
| <li><a href='http://www.ibm.com/software/websphere/'>WebSphere Application Server</a> from |
| <a href='http://www.ibm.com/software/websphere/'>IBM</a> (versions 5 and 6).</li> |
| </ul> |
| <p> |
| Containers suspected to use this mechanism: |
| </p> |
| <ul> |
| <li>WebSphere Application Server (other versions).</li> |
| </ul> |
| <p> |
| The Apache Commons team would be grateful if reports were posted to the development list |
| of other containers using a custom implementation. |
| </p> |
| <subsection name='The Incompatible LogFactory Issue'> |
| <subsection name='Symptoms'> |
| <p> |
| An exception is thrown by JCL with a message similar to: |
| </p> |
| <code><pre> |
| The chosen LogFactory implementation does not extend LogFactory. Please check your configuration. |
| (Caused by java.lang.ClassCastException: The application has specified that a custom LogFactory |
| implementation should be used but Class 'com.ibm.ws.commons.logging.TrLogFactory' cannot be converted |
| to 'org.apache.commons.logging.LogFactory'. The conflict is caused by the presence of multiple |
| LogFactory classes in incompatible classloaders. Background can be found in |
| http://commons.apache.org/logging/tech.html. If you have not explicitly specified a custom |
| LogFactory then it is likely that the container has set one without your knowledge. |
| In this case, consider using the commons-logging-adapters.jar file or specifying the standard |
| LogFactory from the command line. Help can be found @http://commons.apache.org/logging. |
| </pre></code> |
| <p> |
| This is a WebSphere example so the name of the custom LogFactory is |
| <code>com.ibm.ws.commons.logging.TrLogFactory</code>. For other containers, this class name will |
| differ. |
| </p> |
| </subsection> |
| <subsection name='Explanation'> |
| <p> |
| A custom <code>LogFactory</code> implementation can only be used if the implementation class loaded |
| dynamically at runtime can be cast to the <code>LogFactory</code> class that loaded it. There are |
| several ways in which this cast can fail. The most obvious is that the source code may not actually |
| extend <code>LogFactory</code>. The source may be compatible but if the <code>LogFactory</code> class |
| against which the source is compiled is not binary compatible then the cast will also fail. |
| </p> |
| <p> |
| There is also another more unusual way in which this cast can fail: even when the binary is compatible, |
| the implementation class loaded at runtime may be linked to a different instance of the |
| <code>LogFactory</code> class. For more information, see the <a href='tech.html'>tech guide</a>. |
| </p> |
| <p> |
| This situation may be encountered in containers which use a custom <code>LogFactory</code> implementation. |
| The implementation will typically be provided in a shared, high level classloader together with JCL. |
| When an application classloader contains <code>LogFactory</code>, the implementation will be loaded |
| from that higher level classloader. The implementation class will be linked to the <code>LogFactory</code> |
| class loaded by the higher level classloader. Even if the |
| <code>LogFactory</code> implementations are binary compatible, since they are loaded by different classloaders |
| the two <code>LogFactory</code> Class instances are not equal and so the cast must fail. |
| </p> |
| <p> |
| The policy adopted by JCL in this situation is to re-throw this exception. Additional information |
| is included in the message to help diagnosis. The reasoning behind this choice is that a |
| particular <code>LogFactory</code> implementation has been actively specified and this |
| choice should not be ignored. This policy has unfortunate consequences when running in |
| containers which have custom implementations: the above runtime exception may be thrown |
| under certain classloading policies without the user knowingly specifying a custom |
| implementation. |
| </p> |
| </subsection> |
| <subsection name='Fixes'> |
| <p> |
| There are various ways to fix this problem. Which fix is right depends on the circumstances. |
| </p> |
| <p> |
| If you are happy using another classloading policy for the application, select a |
| classloading policy which ensures that <code>LogFactory</code> will be loaded from the |
| shared classloader containing the custom implementation. |
| </p> |
| <p> |
| If you want to bypass the container adaption mechanism then set the appropriate system property |
| to the default value when the container is started: |
| </p> |
| <code><pre> |
| -Dorg.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl |
| </pre></code> |
| <p> |
| If you want to continue to use the default container mechanism then: |
| </p> |
| <ul> |
| <li> |
| Find and replace the commons-logging implementation used by the container with |
| the most modern release |
| </li> |
| <li> |
| Replace the commons-logging jar in the application with the commons-logging-adapters jar. |
| This will ensure that application classloader will delegate to it's parent when loading |
| <code>LogFactory</code>. |
| </li> |
| </ul> |
| <p> |
| If you encounter difficulties when applying the fixes recommended, please turn on |
| <a href='#Using JCL Diagnostics'>diagnostics</a> and consult the logs. |
| </p> |
| </subsection> |
| </subsection> |
| </section> |
| <section name='Containers With Custom ClassLoading Behaviour for Logging'> |
| <p> |
| Because commons-logging is such a fundamental library, some containers modify the way |
| in which classloading behaves for commons-logging classes. |
| </p> |
| <subsection name="Apache Tomcat"> |
| <p> |
| At the current date, Tomcat 5.5.16 is the current release. All releases from version |
| 4.1.x through 5.5.16 have a startup process that places jarfile |
| ${tomcat.home}/bin/commons-logging-api.jar in the system classpath and then |
| prevents any webapp from overriding the classes in that jarfile. Effectively, all |
| webapps behave as if "parent-first" classloading were enabled for those classes. |
| </p> |
| <p> |
| This has some benefits; in particular it means that there are no problems in |
| these Tomcat versions with having multiple copies of the commons-logging Log |
| interface in the classpath (which avoids the "Log does not implement Log" |
| problem described elsewhere). |
| </p> |
| <p> |
| However it also means that no webapp can override the core commons-logging |
| classes by including an updated commons-logging jarfile in WEB-INF/lib; any |
| class already loaded via the container takes priority. In particular, as |
| Tomcat bundles logging 1.0.4 only, the new diagnostics and memory-leak-prevention |
| features of the 1.1 release will not be available unless the container's |
| library version is updated. |
| </p> |
| <p> |
| Because the commons-logging-api.jar in the container does not contain any |
| log-library-adapter classes, updated behaviour for these <i>will</i> be |
| seen when logging 1.1 is bundled in WEB-INF/lib. In particular, the |
| support for log4j's TRACE level will take effect without having to update |
| the container. |
| </p> |
| <p> |
| If you do wish to update Tomcat's version of commons-logging, then you |
| <i>must</i> use the commons-logging-1.1-api jar only, not the full jar. |
| Classes in the webapp cannot override classes loaded from the system |
| classpath set up during Tomcat's startup process, and logging adapters |
| can only see their matching concrete logging library if that library is |
| available in the same classpath. Bundling the full commons-logging jarfile |
| (with adapters) into the system classpath therefore means that logging |
| libraries (eg log4j) within WEB-INF/lib are not accessible. |
| </p> |
| <p> |
| Note that the behaviour described here only applies if the standard Tomcat |
| startup process is run. When Tomcat is embedded in a larger |
| framework (eg run embedded within an IDE) this may not apply. |
| </p> |
| </subsection> |
| <subsection name="JBoss Application Server"> |
| <p> |
| The JBoss Application Server can be configured to prevent deployed |
| code from overriding classes higher in the hierarchy, effectively |
| forcing "parent-first" behaviour for selected classes. By default, |
| commons-logging is in this list (at least for some JBoss versions |
| starting with 4.0.2), and therefore including an updated version |
| of commons-logging in WEB-INF/lib or similar will have no effect. |
| See the JBoss classloading documentation for more details. |
| </p> |
| </subsection> |
| <subsection name="Other Containers"> |
| <p> |
| As more information becomes available on this topic, it may be added |
| to the commons-logging wiki site. |
| </p> |
| </subsection> |
| </section> |
| </body> |
| </document> |