Demonstration/Proof of concept code. Contained is an analysis of common parent first and child first JCL use cases using convention context classloaders together with code that demonstrates the concepts involved.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@159106 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
832
demonstration/src/java/overview.html
Normal file
832
demonstration/src/java/overview.html
Normal file
@@ -0,0 +1,832 @@
|
||||
<html>
|
||||
<!-- $Id: overview.html 132718 2004-09-09 20:38:21Z rdonkin $
|
||||
|
||||
Copyright 2005 The Apache Software Foundation.
|
||||
|
||||
Licensed 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.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=iso-8859-1">
|
||||
<title>Overview Documentation for JCL Proof Of Concept Demonstrations</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Demonstrates Jakarta Commons Logging (JCL) concepts.</h1>
|
||||
<h3>Introduction</h3>
|
||||
<p>This document contains analysis of various JCL use cases. It works
|
||||
both as an educational document and as a specification (of sorts).
|
||||
It's intended audience are (potential) JCL developers and (potential)
|
||||
expert users. The code that accompanies
|
||||
this document demonstrates the cases analysed in the text.
|
||||
</p>
|
||||
<p>Familiarity with (advanced) class loading
|
||||
concepts and terminology is assumed. Please digest the
|
||||
<a HREF="http://jakarta.apache.org/commons/logging/tech.html">JCL
|
||||
Technology Guide</a> before starting.
|
||||
</p>
|
||||
<p>This approach was inspired by a JCL critique written by Ceki
|
||||
Guici.
|
||||
</p>
|
||||
<p>These demonstrations focus on discovery in general and discovery
|
||||
of Log4J in particular. Not only is Log4J the most important target
|
||||
but these are some of the most difficult and contentious cases.
|
||||
Lessons learnt from these cases should easily and safely extrapolate
|
||||
to other cases.
|
||||
</p>
|
||||
<p>It is important that this document is as accurate as possible both
|
||||
in facts and analysis. Readers are encouraged to contribute
|
||||
corrections and improvements. Please either:
|
||||
</p>
|
||||
<ul>
|
||||
<li>submit a <A HREF="http://issues.apache.org/bugzilla">bug
|
||||
report</a> for the JCL component</li>
|
||||
<li>or post to the Jakarta Commons Developer <a href="http://jakarta.apache.org/site/mail.html">mailing
|
||||
list</a></li>
|
||||
</p>
|
||||
</ul>
|
||||
<h3>Overview</h3>
|
||||
<p>The basic set up for these demonstrations is intentionally simple.
|
||||
There are no tricks that might obscure a clear view of the concepts.
|
||||
The source code used to run these demonstrations is simple and should
|
||||
be easy to understand.
|
||||
</p>
|
||||
<p>Each demonstration is initiated by a runner. The runner loads the
|
||||
other code components into appropriate ClassLoaders and then calls the caller.
|
||||
</p>
|
||||
<p>The caller is used to simulate a class that needs to log
|
||||
something. It is isolated from the code that runs the demonstration
|
||||
in order to allow a greater variety of ClassLoader situations to be simulated.
|
||||
The calling code is split
|
||||
into one class that presents the formatted results and another that
|
||||
actually performs the calls. Calls are made to JCL and to a static
|
||||
logger.
|
||||
</p>
|
||||
<p>The static logger simply contains a call directly to Log4J. This
|
||||
is useful for comparison.
|
||||
</p>
|
||||
<p>Now would be a good idea to study the javadocs.
|
||||
</p>
|
||||
<p>Results are printed (with a little formatting) to System.out. The
|
||||
run target in the ant build scripts runs all cases. It may be
|
||||
difficult to run these demonstrations from an IDE (a clean system
|
||||
ClassLoader is required).
|
||||
</p>
|
||||
<h4>Conventional And Unconventional Context ClassLoaders</h4>
|
||||
<p>This analysis will start by making a division between conventional
|
||||
context classloaders and unconventional ones. Conventionally, the
|
||||
context classloader for a thread executing code in a particular class
|
||||
should either be the classloader used to load the class, an ancestor
|
||||
of that classloader or a descendent of it. The conventional context
|
||||
classloader cases will focus on context classloaders which obey these
|
||||
rules.
|
||||
</p>
|
||||
<h3>Conventional Classloader Cases</h3>
|
||||
<p>The aim of the set up will be isolate the essentials. Only three
|
||||
classloaders will be considered:
|
||||
</p>
|
||||
<ul>
|
||||
<li>the system classloader,</li>
|
||||
<li>a parent classloader (whose parent
|
||||
is the system classloader) </li>
|
||||
<li>and a child classloader of the parent.</li>
|
||||
</ul>
|
||||
<p>This situation is commonly encountered in containers (where the
|
||||
child classloader is the application classloader). In practical
|
||||
situations, the hierarchy is likely to be contain more classloaders
|
||||
but it should be possible either to extrapolate from these simple
|
||||
cases or reduce the more complex ones to these.
|
||||
</p>
|
||||
<p>The analysis will proceed by considering two cases separately:
|
||||
</p>
|
||||
<ul>
|
||||
<li>parent-first classloading </li>
|
||||
<li>and child-first classloading.</li>
|
||||
</ul>
|
||||
<p>In the parent first cases, when the child classloader initiates
|
||||
loading, it starts by delegating to the parent classloader. Only if
|
||||
this classloader does not define the class will the child classloader
|
||||
attempt to define the class. In the child first cases, the child
|
||||
classloader will begin by attempting to define the class itself. Only
|
||||
when it cannot define a class will it delegate to it's parents.
|
||||
Further discussion of each of these cases will be contained in the
|
||||
appropriate section.
|
||||
</p>
|
||||
<p>The other variable is the setting of the context classloader. In
|
||||
these cases, it will be set to either the system classloader (the
|
||||
default) or the child classloader (the application classloader).
|
||||
Perhaps the cases for setting to the parent classloader
|
||||
should be added (but this would be unusual: conventionally the context
|
||||
classloader should be either unset or set to the application
|
||||
classloader). Contributions of these extra cases would be welcomed.
|
||||
</p>
|
||||
<p>The cases will be presented in a matrix. This contains details of
|
||||
the classloader set ups including which
|
||||
which classes are definable by which loaders and how the context
|
||||
classloader is set. It also contains the results of analysis about
|
||||
the way that both the static logging and JCL (ideally) should behave.
|
||||
</p>
|
||||
<p>For example
|
||||
</p>
|
||||
<table border='1'>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>JCL+Static</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>
|
||||
JCL+Static<br/>
|
||||
Log4J<br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>This describes a case where the context classloader is unset (and
|
||||
so defaults to the system), the static.jar and commons-logging.jar
|
||||
are definable by the parent classloader, the static.jar,
|
||||
commons-logging.jar and log4j are definable by the child. The
|
||||
caller.jar is also definable by the child classloader. The expected
|
||||
result in this case is that JCL will discover java.util.logging and
|
||||
that logging statically to Log4j will fail.
|
||||
</p>
|
||||
<p>For purposes of reference, an indication is given in those cases
|
||||
that correspond to examples used by Ceki in his critique.
|
||||
</p>
|
||||
<p>Analytical notes explaining how these results were obtained are
|
||||
included below each table. As the cases proceed, the notes will grow
|
||||
more terse.
|
||||
</p>
|
||||
<h4>Parent First ClassLoader Cases</h4>
|
||||
<h5>Log4J Defined By Child, JCL By Parent</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>1</td>
|
||||
<td>2A</td>
|
||||
<td>3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>JCL+Static</td>
|
||||
<td>JCL+Static Caller</td>
|
||||
<td>JCL+Static</td>
|
||||
<td>JCL+Static Caller</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>
|
||||
JCL+Static<br/>
|
||||
Log4J<br/>
|
||||
Caller</td>
|
||||
<td>
|
||||
JCL+Static<br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>
|
||||
JCL+Static<br/>
|
||||
Log4J<br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>
|
||||
JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>
|
||||
JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>
|
||||
JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>
|
||||
JCL->java.util <br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>
|
||||
JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>One important point to bear in mind when analysing parent-first
|
||||
classloaders is that the presence or absence in the child classloader
|
||||
of classes definable by the parent classloader produces no difference
|
||||
in behaviour: the parent classloader will always load the class in
|
||||
question.
|
||||
</p>
|
||||
<p>In the cases above, Log4J is defined (only) by the child and all
|
||||
JCL classes by the parent classloader. The symbolic references from
|
||||
Log4JLogger to Log4J classes therefore cannot be resolved as Log4j is
|
||||
not definable by the parent classloader. For the same reason, the
|
||||
static call should also always fail.
|
||||
</p>
|
||||
<p>The context classloader can be of no use (whether set or not)
|
||||
since Log4JLogger will always be defined by the parent classloader
|
||||
whether loading is initiated by the child or by the parent loader.
|
||||
</p>
|
||||
<p>Therefore, in these cases, the appropriate behaviour is for JCL to
|
||||
discover that java.util.logging is the only available logging system.
|
||||
</p>
|
||||
<h5>Log4J Defined By Parent, JCL By Parent</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static
|
||||
<td>Log4J <br/>
|
||||
JCL+Static <br/>
|
||||
Caller
|
||||
<td>Log4J <br/>
|
||||
JCL+Static
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static<br/>
|
||||
Log4J <br/>
|
||||
Caller <br/>
|
||||
</td>
|
||||
<td>JCL+Static<br/>
|
||||
Log4J <br/>
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J<br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static<br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result
|
||||
</th>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>
|
||||
JCL->log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>
|
||||
JCL->log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>This demonstrates the usual way to fix the problems encountered
|
||||
when Log4J is not definable by the loader that defines JCL: just add
|
||||
the Log4j.jar into the classloader that defines JCL.
|
||||
</p>
|
||||
<p>This is a very simple set of cases with JCL and static being able
|
||||
to resolve the appropriate symbolic references to Log4j directly.
|
||||
Whether the context classloader is set or not in these cases should
|
||||
make no difference.
|
||||
</p>
|
||||
<h5>Log4J Defined By Child, JCL API By Parent, JCL By Child</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>API+Static</td>
|
||||
<td>API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>API+Static
|
||||
</td>
|
||||
<td>API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static<br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>JCL->log4j<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static FAIL</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>These demonstrate variations on the first series of cases where
|
||||
Log4J is defined by the child. The placement of the static jar does
|
||||
not vary (from the previous set) and again is expected to
|
||||
consistently fail.
|
||||
</p>
|
||||
<p>This time the API jar is placed in the parent classloader and the
|
||||
full JCL jar in the child. This means that the symbolic reference
|
||||
from the Log4JLogger class (contained in the full jar but not the
|
||||
API) to Log4J classes can be resolved.
|
||||
</p>
|
||||
<p>In these cases, whether JCL can succeed depends on the context
|
||||
classloader. The delegation model employed by Java ClassLoaders
|
||||
allows child classloaders to know about parents but not vice versa.
|
||||
Therefore, the context classloader is the only means available to
|
||||
attempt to load Log4JLogger. When the context classloader is set to
|
||||
the child, this classloader defines Log4JLogger and Log4J. Therefore,
|
||||
JCL should be able to discover Log4J (only) when the context
|
||||
classloader is set to the child.
|
||||
</p>
|
||||
<h5>Log4J Defined By Parent, JCL API By Parent, JCL By Child</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
<td>16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>Log4J <br/>
|
||||
API+Static
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>Log4J<br/>
|
||||
API+Static
|
||||
</td>
|
||||
<td>Log4J<br/>
|
||||
API+Static<br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static<br/>
|
||||
Log4J <br/>
|
||||
Caller</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->log4j<br/>
|
||||
static OK</td>
|
||||
<td>JCL->log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Trivial variations on the second series. Now API and JCL are
|
||||
definable only by parent and child respectively (as in the last
|
||||
series).
|
||||
</p>
|
||||
<h4>Child First ClassLoader Cases</h4>
|
||||
<p>The same classloader configuration can be repeated with (this
|
||||
time) child-first classloading.
|
||||
</p>
|
||||
<h5>Log4J Defined By Child, JCL By Parent</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>17</td>
|
||||
<td>18</td>
|
||||
<td>19</td>
|
||||
<td>20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>JCL+Static</td>
|
||||
<td>JCL+Static <br/>
|
||||
Caller</td>
|
||||
<td>JCL+Static</td>
|
||||
<td>JCL+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->Log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util <br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>JCL->Log4j<br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util<br/>
|
||||
static FAIL
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>In child-first cases, the classloader which defines the caller
|
||||
plays a more important role. When the caller is defined by the child
|
||||
classloader, both static and JCL should succeed whether the context
|
||||
classloader is set or not.
|
||||
</p>
|
||||
<p>When the caller is defined by the parent classloader, this means
|
||||
that the parent classloader will define the JCL and static classes
|
||||
(rather than the child). Log4J is not defined by the parent loader
|
||||
and so the static call must fail in both cases.
|
||||
</p>
|
||||
<p>With a friendly context classloader, JCL can load an instance of
|
||||
Log4JLogger whose symbolic references to Log4J can be resolved.
|
||||
However, the child classloader which defines this class will resolve
|
||||
the symbolic reference to Log to the class defined by the child
|
||||
classloader rather than the Log class defined by the parent
|
||||
classloader. They are not mutually accessible and so JCL must
|
||||
discover java.util.logging.
|
||||
</p>
|
||||
<h5>Log4J Defined By Parent, JCL By Parent</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case
|
||||
</th>
|
||||
<td>21</td>
|
||||
<td>22</td>
|
||||
<td>23</td>
|
||||
<td>24</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
JCL+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Trivial case where jar's are definable by both loaders.
|
||||
</p>
|
||||
<h5>Log4J Defined By Child, JCL API By Parent, JCL By Child</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>25</td>
|
||||
<td>26</td>
|
||||
<td>27</td>
|
||||
<td>28</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>API+Static</td>
|
||||
<td>API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>API+Static</td>
|
||||
<td>API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util <br/>
|
||||
static FAIL
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util <br/>
|
||||
static FAIL
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>(As above) to succeed, the static call requires that Log4J is
|
||||
definable by the loader which defines the callers. JCL should
|
||||
discover Log4J in the cases where the static call succeeds.
|
||||
</p>
|
||||
<p>Even with a friendly context classloader, the Log class referenced
|
||||
by the Log4JLogger defined by the child classloader will be
|
||||
inaccessible to the caller (loader by the parent classloader).
|
||||
</p>
|
||||
<h5>Log4J Defined By Parent, JCL API By Parent, JCL By Child</h5>
|
||||
<table border='1' width='90%'>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<td>29</td>
|
||||
<td>30</td>
|
||||
<td>31</td>
|
||||
<td>32</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ceki Example</th>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Context ClassLoader</th>
|
||||
<td>System</td>
|
||||
<td>System</td>
|
||||
<td>Child</td>
|
||||
<td>Child</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parent</th>
|
||||
<td>Log4J <br/>
|
||||
API+Static
|
||||
</td>
|
||||
<td>Log4J <br/>
|
||||
API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>Log4J<br/>
|
||||
API+Static
|
||||
</td>
|
||||
<td>Log4J<br/>
|
||||
API+Static <br/>
|
||||
Caller
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Child</th>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J <br/>
|
||||
Caller
|
||||
</td>
|
||||
<td>JCL+Static <br/>
|
||||
Log4J
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expected Result</th>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->log4j <br/>
|
||||
static OK
|
||||
</td>
|
||||
<td>JCL->java.util <br/>
|
||||
static OK
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>These results at first glance may seem a little confusing. The
|
||||
issue for JCL is that classes needed to log to Log4J are only
|
||||
definable by the child classloader.
|
||||
</p>
|
||||
<p>Even with a friendly context classloader, JCL runs into the same
|
||||
difficulties with accessibility that
|
||||
occurred above.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user