diff --git a/project.xml b/project.xml
index 8ba75b8..d4ae817 100644
--- a/project.xml
+++ b/project.xml
@@ -88,13 +88,13 @@
JCL provides thin-wrapper Log implementations for
other logging tools, including
-Log4J,
-Avalon LogKit,
+Log4J,
+Avalon LogKit,
the Avalon Framework's logging infrastructure,
JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4
systems.
@@ -143,16 +143,16 @@ compatibility to pre-1.0 versions of this API, a system property
@@ -176,7 +176,7 @@ logging toolkit being used. Please consult the documentation for the chosen logg
Log4J is a very commonly used logging implementation (as well as being the JCL primary default), so a few details are presented herein to get the developer/integrator going. -Please see the Log4J Home for more details +Please see the Log4J Home for more details on Log4J and it's configuration.
@@ -314,8 +314,8 @@ In addition to the logging methods, the following are provided for code guards:
The commons-logging.jar file includes the JCL API, the default
LogFactory implemenation and thin-wrapper Log
implementations for
-Log4J,
-Avalon LogKit,
+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.
@@ -352,7 +352,7 @@ 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
+Tomcat that wish to use
JCL internally but also need to make JCL available for use by deployed
applications.
-Please download and test this release. Reports should be directed to the commons-dev +Please download and test this release. Reports should be directed to the commons-dev mailing list.
@@ -92,10 +92,8 @@ signature of the release from the when downloading from a mirror.
- Binary releases are available - here. - Source releases are available - here + Binary and source releases are available + here.
diff --git a/xdocs/tech.xml b/xdocs/tech.xml index 72841a0..eef3246 100644 --- a/xdocs/tech.xml +++ b/xdocs/tech.xml @@ -1,658 +1,658 @@ - - - - -
- This guide is aimed at describing the technologies that JCL developers and expert users - (and users who need to become experts) - should be familiar with. The aim is to give an understanding whilst being precise but brief. - Details which are not relevent for JCL have been suppressed. - References have been included. -
-- These topics are a little difficult and it's easy for even experience developers to make - mistakea. We need you to help us get it right! Please submit corrections, comments, additional references - and requests for clarification - by either: -
-- TIA -
-- This is intended to present a guide to the process by which Java bytecode uses bytecode in other classes - from the perspective of the language and virtual machine specifications. The focus will be on deciding - which bytecode will be used (rather than the mechanics of the usage). It focusses on facts and terminology. -
-- The process is recursive: it is therefore difficult to pick a starting point. - Sun's documentation starts from the persective of the startup of a new application. - This guide starts from the perspective of an executing application. -
-- During this discussion, please assume that each time that class is mentioned, - the comments applied equally well to interfaces. -
-- This document is targeted at Java 1.2 and above. -
-- (LangSpec 12.3.3) - The bytecode representation of a class contains symbolic names for other classes referenced. -
-- - In practical development terms: If a class is imported (either explicitly in the list of imports at the top of - the source file or implicitly through a fully qualified name in the source code) it is referenced symbolically. - -
-- (VMSpec 5.4.3) - Resolution of a symbolic reference occurs dymanically at runtime and is carried out by - the Java Vitual Machine. Resolution of a symbolic reference requires loading and linking of the new class. -
-- - Note: references are not statically resolved at compile time. - -
-- (VMSpec 2.17.2) - Loading is the name given process by which a binary form of a class is obtained - by the Java Virutal Machine. - Java classes are always loaded and linked dynamically by the Java Virtual Machine - (rather than statically by the compiler). -
-- - In practical development terms: - This means that the developer has no certain knowledge about the actual - bytecode that will be used to execute any external call (one made outside the class). This is determined only - at execution time and is effected by the way that the code is deployed. - -
-- (VMSpec 2.17.3) - Linking is the name used for combining the - binary form of a class into the Java Virtual Machine. This must happen before the class can be used. -
-- (VMSpec 2.17.3) - Linking is composed of verification, preparation and resolution (of symbolic references). - Flexibility is allowed over the timing of resolution. (Within limit) this may happen at any time after - preparation and before that reference is used. -
-- - In practical development terms: This means that different JVMs may realize that a reference cannot be - resolved at different times during execution. Consequently, the actual behaviour cannot be precisely predicted - without intimate knowledge of the JVM (on which the bytecode will be executed). - This makes it hard to give universal guildance to users. - -
-
- (VMSpec 2.17.2)
- The loading process is performed by a ClassLoader.
-
- (VMSpec 5.3) - A classloader may create a class either by delegation or by defining it directly. - The classloader that initiates loading of a class is known as the initiating loader. - The classloader that defines the class is known as the defining loader. -
-- - In practical terms: understanding and appreciating this distinction is crucial when debugging issues - concerning classloaders. - -
-
- (VMSPEC 5.3)
- The bootstrap is the base ClassLoader supplied by the Java Virtual Machine.
- All others are user (also known as application) ClassLoader's.
-
-
- In practical development terms: The System classloader returned by Classloader.getSystemClassLoader()
- will be either the bootstrap classloader or a direct descendent of the bootstrap classloader.
- Only when debugging issues concerning the system classloader should there be any need to consider the detailed
- differences between the bootstrap classloader and the system classloader.
-
-
- (VMSpec 5.3) - At runtime, a class (or interface) is determined by it's fully qualified name - and by the classloader that defines it. This is known as the class's runtime package. -
-- (VMSpec 5.4.4) - Only classes in the same runtime package are mutually accessible. -
-- - In practical development terms: two classes with the same symbolic name can only be used interchangably - if they are defined by the same classloader. A classic symptom indicative of a classloader issue is that - two classes with the same fully qualified name are found to be incompatible during a method call. - This may happen when a member is expecting an interface which is (seemingly) implemented by a class - but the class is in a different runtime package after being defined by a different classloader. This is a - fundemental java language security feature. - -
-- (VMSpec 5.3) - The classloader which defines the class (whose reference is being resolved) is the one - used to initiate loading of the class referred to. -
-- - In practial development terms: This is very important to bear in mind when trying to solve classloader issues. - A classic misunderstanding is this: suppose class A defined by classloader C has a symbolic reference to - class B and further that when C initiates loading of B, this is delegated to classloader D which defines B. - Class B can now only resolve symbols that can be loaded by D, rather than all those which can be loaded by C. - This is a classic recipe for classloader problems. - -
-
- When asked to load a class, a class loader may either define the class itself or delegate.
- The base ClassLoader class insists that every implementation has a parent class loader.
- This delegation model therefore naturally forms a tree structure rooted in the bootstrap classloader.
-
- Containers (i.e. applications such as servlet engines or application servers - that manage and provide support services for a number of "contained" applications - that run inside of them) often use complex trees to allow isolation of different applications - running within the container. This is particularly true of J2EE containers. -
-- When a classloader is asked to load a class, a question presents itself: should it immediately - delegate the loading to it's parent (and thus only define those classes not defined by it's parent) - or should it try to define it first itself (and only delegate to it's parent those classes it does - not itself define). Classloaders which universally adopt the first approach are termed parent-first - and the second child-first. -
-- Note: the term child-first (though commonly used) is misleading. - A better term (and one which may be encountered on the mailing list) is parent-last. - This more accurately describes the actual process of classloader performed - by such a classloader. -
-
- Parent-first loading has been the standard mechanism in the JDK
- class loader, at least since Java 1.2 introduced hierarchical classloaders.
- The primary reason for this is safety -- parent-first
- makes it impossible for malicious code to trick the JVM into
- replacing a core class (say, java.security.SecurityManager) with a
- class of the same name loaded from a child classloader.
-
- Child-first classloading has the advantage of helping to improve isolation
- between containers and the applications inside them. If an application
- uses a library jar that is also used by the container, but the version of
- the jar used by the two is different, child-first classloading allows the
- contained application to load its version of the jar without affecting the
+
+
+
+
+
+ This guide is aimed at describing the technologies that JCL developers and expert users
+ (and users who need to become experts)
+ should be familiar with. The aim is to give an understanding whilst being precise but brief.
+ Details which are not relevent for JCL have been suppressed.
+ References have been included.
+
+ These topics are a little difficult and it's easy for even experience developers to make
+ mistakea. We need you to help us get it right! Please submit corrections, comments, additional references
+ and requests for clarification
+ by either:
+
+ TIA
+
+ This is intended to present a guide to the process by which Java bytecode uses bytecode in other classes
+ from the perspective of the language and virtual machine specifications. The focus will be on deciding
+ which bytecode will be used (rather than the mechanics of the usage). It focusses on facts and terminology.
+
+ The process is recursive: it is therefore difficult to pick a starting point.
+ Sun's documentation starts from the persective of the startup of a new application.
+ This guide starts from the perspective of an executing application.
+
+ During this discussion, please assume that each time that class is mentioned,
+ the comments applied equally well to interfaces.
+
+ This document is targeted at Java 1.2 and above.
+
+ (LangSpec 12.3.3)
+ The bytecode representation of a class contains symbolic names for other classes referenced.
+
+
+ In practical development terms: If a class is imported (either explicitly in the list of imports at the top of
+ the source file or implicitly through a fully qualified name in the source code) it is referenced symbolically.
+
+
+ (VMSpec 5.4.3)
+ Resolution of a symbolic reference occurs dymanically at runtime and is carried out by
+ the Java Vitual Machine. Resolution of a symbolic reference requires loading and linking of the new class.
+
+
+ Note: references are not statically resolved at compile time.
+
+
+ (VMSpec 2.17.2)
+ Loading is the name given process by which a binary form of a class is obtained
+ by the Java Virutal Machine.
+ Java classes are always loaded and linked dynamically by the Java Virtual Machine
+ (rather than statically by the compiler).
+
+
+ In practical development terms:
+ This means that the developer has no certain knowledge about the actual
+ bytecode that will be used to execute any external call (one made outside the class). This is determined only
+ at execution time and is effected by the way that the code is deployed.
+
+
+ (VMSpec 2.17.3)
+ Linking is the name used for combining the
+ binary form of a class into the Java Virtual Machine. This must happen before the class can be used.
+
+ (VMSpec 2.17.3)
+ Linking is composed of verification, preparation and resolution (of symbolic references).
+ Flexibility is allowed over the timing of resolution. (Within limit) this may happen at any time after
+ preparation and before that reference is used.
+
+
+ In practical development terms: This means that different JVMs may realize that a reference cannot be
+ resolved at different times during execution. Consequently, the actual behaviour cannot be precisely predicted
+ without intimate knowledge of the JVM (on which the bytecode will be executed).
+ This makes it hard to give universal guildance to users.
+
+
+ (VMSpec 2.17.2)
+ The loading process is performed by a
+ (VMSpec 5.3)
+ A classloader may create a class either by delegation or by defining it directly.
+ The classloader that initiates loading of a class is known as the initiating loader.
+ The classloader that defines the class is known as the defining loader.
+
+
+ In practical terms: understanding and appreciating this distinction is crucial when debugging issues
+ concerning classloaders.
+
+
+ (VMSPEC 5.3)
+ The bootstrap is the base
+
+ In practical development terms: The System classloader returned by
+ (VMSpec 5.3)
+ At runtime, a class (or interface) is determined by it's fully qualified name
+ and by the classloader that defines it. This is known as the class's runtime package.
+
+ (VMSpec 5.4.4)
+ Only classes in the same runtime package are mutually accessible.
+
+
+ In practical development terms: two classes with the same symbolic name can only be used interchangably
+ if they are defined by the same classloader. A classic symptom indicative of a classloader issue is that
+ two classes with the same fully qualified name are found to be incompatible during a method call.
+ This may happen when a member is expecting an interface which is (seemingly) implemented by a class
+ but the class is in a different runtime package after being defined by a different classloader. This is a
+ fundemental java language security feature.
+
+
+ (VMSpec 5.3)
+ The classloader which defines the class (whose reference is being resolved) is the one
+ used to initiate loading of the class referred to.
+
+
+ In practial development terms: This is very important to bear in mind when trying to solve classloader issues.
+ A classic misunderstanding is this: suppose class A defined by classloader C has a symbolic reference to
+ class B and further that when C initiates loading of B, this is delegated to classloader D which defines B.
+ Class B can now only resolve symbols that can be loaded by D, rather than all those which can be loaded by C.
+ This is a classic recipe for classloader problems.
+
+
+ When asked to load a class, a class loader may either define the class itself or delegate.
+ The base
+ Containers (i.e. applications such as servlet engines or application servers
+ that manage and provide support services for a number of "contained" applications
+ that run inside of them) often use complex trees to allow isolation of different applications
+ running within the container. This is particularly true of J2EE containers.
+
+ When a classloader is asked to load a class, a question presents itself: should it immediately
+ delegate the loading to it's parent (and thus only define those classes not defined by it's parent)
+ or should it try to define it first itself (and only delegate to it's parent those classes it does
+ not itself define). Classloaders which universally adopt the first approach are termed parent-first
+ and the second child-first.
+
+ Note: the term child-first (though commonly used) is misleading.
+ A better term (and one which may be encountered on the mailing list) is parent-last.
+ This more accurately describes the actual process of classloader performed
+ by such a classloader.
+
+ Parent-first loading has been the standard mechanism in the JDK
+ class loader, at least since Java 1.2 introduced hierarchical classloaders.
+ The primary reason for this is safety -- parent-first
+ makes it impossible for malicious code to trick the JVM into
+ replacing a core class (say,
+ Child-first classloading has the advantage of helping to improve isolation
+ between containers and the applications inside them. If an application
+ uses a library jar that is also used by the container, but the version of
+ the jar used by the two is different, child-first classloading allows the
+ contained application to load its version of the jar without affecting the
container.
-
- The ability for a servlet container to offer child-first classloading
- is made available, as an option, by language in the servlet spec (Section
- 9.7.2) that allows a container to offer child-first loading with
- certain restrictions, such as not allowing replacement of java.* or
- javax.* classes, or the container's implementation classes.
-
- Though child-first and parent-first are not the only strategies possible,
- they are by far the most common.
- All other strategies are rare.
- However, it is not uncommon to be faced with a mixture of parent-first and child-first
- classloaders within the same hierarchy.
-
- The class loader used to define a class is available programmatically by calling
- the
- Java 1.2 introduces a mechanism which allows code to access classloaders
- which are not the class classloader or one of its parents.
- A thread may have a class loader associated with it by it's creator for use
- by code running in the thread when loading resources and classes.
- This classloader is accessed by the
- Note that the quality and appropriateness of the context classloader depends on the
- care with which the thread's owner manages it.
-
- The Javadoc for
-
-
- For example, in a hypothetical servlet container, a pool of threads
- is created to handle HTTP requests. When created these threads have their
- context classloader set to a classloader that loads container classes.
- After the thread is assigned to handle a request, container code parses
- the request and then determines which of the deployed web applications
- should handle it. Only when the container is about to call code associated
- with a particular web application (i.e. is about to cross an "application
- boundary") is the context classloader set to the classloader used to load
- the web app's classes. When the web application finishes handling the
- request and the call returns, the context classloader is set back to the
- container classloader.
-
- In a properly managed container, changes in the context classloader are
- made when code execution crosses an application boundary. When contained
- application
- While a contained application is handling a request, it is not
- unusual for it to call system or library code loaded by the container.
- For example, a contained application may wish to call a utility function
- provided by a shared library. This kind of call is considered to be
- within the "application boundary", so the context classloader remains
- the contained application's classloader. If the system or library code
- needs to load classes or other resources only visible to the contained
- application's classloader, it can use the context classloader to access
- these resources.
-
- If the context classloader is properly managed, system and library code
- that can be accessed by multiple applications can not only use it to load
- application-specific resources, but also can use it to detect which
- application is making a call and thereby provided services tailored to the
- caller.
-
- In practice, context classloaders vary in quality and issues sometimes arise
- when using them.
- The owner of the thread is responsible for setting the classloader.
- If the context classloader is not set then it will default to the system
- classloader.
- Any container doing so will cause difficulties for any code using the context classloader.
-
- The owner is also at liberty to set the classloader as they wish.
- Containers may set the context classloader so that it is neither a child nor a parent
- of the classloader that defines the class using that loader.
- Again, this will cause difficulties.
-
- Introduced in Java J2EE 1.3
- is a requirement for vendors to appropriately set the context classloader.
- Section 6.2.4.8 (1.4 text):
-
- This specification leaves quite a lot of freedom for vendors.
- (As well as using unconventional terminology and containing the odd typo.)
- It is a difficult passage (to say the least).
-
- Reflection cannot bypass restrictions imposed by the java language security model, but, by avoiding symbolic
- references, reflection can be used to load classes which could not otherwise be loaded. Another
- Recall that the runtime packaging is used to determine accessibility.
- Reflection cannot be used to avoid basic java security.
- Therefore, the runtime packaging becomes an issue when attempting to cast classes
- created by reflection using other class loaders.
- When using this strategy, various modes of failure are possible
- when common class references are defined by the different class loaders.
-
- Reflection is often used with the context classloader. In theory, this allows a class defined in
- a parent classloader to load any class that is loadable by the application.
- In practice, this only works well when the context classloader is set carefully.
-
- JCL takes the view that different context class loader indicate boundaries between applications
- running in a container environment. Isolation requires that JCL honours these boundaries
- and therefore allows different isolated applications to configure their logging systems
- independently.
-
- Performance dictates that symbolic references to these classes are present in the calling application code
- (reflection would simply be too slow). Therefore, these classes must be loadable by the classloader
- that loads the application code.
-
- Performance dictates that symbolic references to the logging systems are present in the implementation
- classes (again, reflection would simply be too slow). So, for an implementation to be able to function,
- it is neccessary for the logging system to be loadable by the classloader that defines the implementing class.
-
- However, there is actually no reason why
- JCL uses the context classloader to use the
+
+
+
+
+
+
+
+
+
+ ClassLoader.
+ ClassLoader supplied by the Java Virtual Machine.
+ All others are user (also known as application) ClassLoader's.
+ Classloader.getSystemClassLoader()
+ will be either the bootstrap classloader or a direct descendent of the bootstrap classloader.
+ Only when debugging issues concerning the system classloader should there be any need to consider the detailed
+ differences between the bootstrap classloader and the system classloader.
+
+ ClassLoader class insists that every implementation has a parent class loader.
+ This delegation model therefore naturally forms a tree structure rooted in the bootstrap classloader.
+ java.security.SecurityManager) with a
+ class of the same name loaded from a child classloader.
+ getClassLoader method
- on the class in question. This is often known as the class classloader.
- getContextClassLoader
- method on Thread. It is therefore often known as the context classloader.
- Thread.setContextClassLoader emphasizes the setting of the
- context classloader as an aspect of thread creation. However, in many
- applications the context classloader is not fixed at thread creation but
- rather is changed throughout the life of thread as thread execution moves
- from one context to another. This usage of the context classloader is
- particularly important in container applications.
- A is handling a request, the context classloader
- should be the one used to load A's resources. When application
- B is handling a request, the context classloader should be
- B's.
- ClassLoader
- can be used to load a class and then reflection used to create an instance.
-
-
- LogFactory requires symbolic references to particular Log
- implementations. Reflection can be used to load these from an appropriate classloader
- without unacceptable performance degradation.
- This is the strategy adopted by JCL.
- Log implementation.
-
+ The ability for a servlet container to offer child-first classloading + is made available, as an option, by language in the servlet spec (Section + 9.7.2) that allows a container to offer child-first loading with + certain restrictions, such as not allowing replacement of java.* or + javax.* classes, or the container's implementation classes. +
++ Though child-first and parent-first are not the only strategies possible, + they are by far the most common. + All other strategies are rare. + However, it is not uncommon to be faced with a mixture of parent-first and child-first + classloaders within the same hierarchy. +
+
+ The class loader used to define a class is available programmatically by calling
+ the getClassLoader method
+ on the class in question. This is often known as the class classloader.
+
+ Java 1.2 introduces a mechanism which allows code to access classloaders
+ which are not the class classloader or one of its parents.
+ A thread may have a class loader associated with it by it's creator for use
+ by code running in the thread when loading resources and classes.
+ This classloader is accessed by the getContextClassLoader
+ method on Thread. It is therefore often known as the context classloader.
+
+ Note that the quality and appropriateness of the context classloader depends on the + care with which the thread's owner manages it. +
+
+ The Javadoc for
+
+ Thread.setContextClassLoader emphasizes the setting of the
+ context classloader as an aspect of thread creation. However, in many
+ applications the context classloader is not fixed at thread creation but
+ rather is changed throughout the life of thread as thread execution moves
+ from one context to another. This usage of the context classloader is
+ particularly important in container applications.
+
+ For example, in a hypothetical servlet container, a pool of threads + is created to handle HTTP requests. When created these threads have their + context classloader set to a classloader that loads container classes. + After the thread is assigned to handle a request, container code parses + the request and then determines which of the deployed web applications + should handle it. Only when the container is about to call code associated + with a particular web application (i.e. is about to cross an "application + boundary") is the context classloader set to the classloader used to load + the web app's classes. When the web application finishes handling the + request and the call returns, the context classloader is set back to the + container classloader. +
+
+ In a properly managed container, changes in the context classloader are
+ made when code execution crosses an application boundary. When contained
+ application A is handling a request, the context classloader
+ should be the one used to load A's resources. When application
+ B is handling a request, the context classloader should be
+ B's.
+
+ While a contained application is handling a request, it is not + unusual for it to call system or library code loaded by the container. + For example, a contained application may wish to call a utility function + provided by a shared library. This kind of call is considered to be + within the "application boundary", so the context classloader remains + the contained application's classloader. If the system or library code + needs to load classes or other resources only visible to the contained + application's classloader, it can use the context classloader to access + these resources. +
++ If the context classloader is properly managed, system and library code + that can be accessed by multiple applications can not only use it to load + application-specific resources, but also can use it to detect which + application is making a call and thereby provided services tailored to the + caller. +
++ In practice, context classloaders vary in quality and issues sometimes arise + when using them. + The owner of the thread is responsible for setting the classloader. + If the context classloader is not set then it will default to the system + classloader. + Any container doing so will cause difficulties for any code using the context classloader. +
++ The owner is also at liberty to set the classloader as they wish. + Containers may set the context classloader so that it is neither a child nor a parent + of the classloader that defines the class using that loader. + Again, this will cause difficulties. +
++ Introduced in Java J2EE 1.3 + is a requirement for vendors to appropriately set the context classloader. + Section 6.2.4.8 (1.4 text): +
++ This specification leaves quite a lot of freedom for vendors. + (As well as using unconventional terminology and containing the odd typo.) + It is a difficult passage (to say the least). +
+
+ Reflection cannot bypass restrictions imposed by the java language security model, but, by avoiding symbolic
+ references, reflection can be used to load classes which could not otherwise be loaded. Another ClassLoader
+ can be used to load a class and then reflection used to create an instance.
+
+ Recall that the runtime packaging is used to determine accessibility. + Reflection cannot be used to avoid basic java security. + Therefore, the runtime packaging becomes an issue when attempting to cast classes + created by reflection using other class loaders. + When using this strategy, various modes of failure are possible + when common class references are defined by the different class loaders. +
++ Reflection is often used with the context classloader. In theory, this allows a class defined in + a parent classloader to load any class that is loadable by the application. + In practice, this only works well when the context classloader is set carefully. +
++ JCL takes the view that different context class loader indicate boundaries between applications + running in a container environment. Isolation requires that JCL honours these boundaries + and therefore allows different isolated applications to configure their logging systems + independently. +
++ Performance dictates that symbolic references to these classes are present in the calling application code + (reflection would simply be too slow). Therefore, these classes must be loadable by the classloader + that loads the application code. +
++ Performance dictates that symbolic references to the logging systems are present in the implementation + classes (again, reflection would simply be too slow). So, for an implementation to be able to function, + it is neccessary for the logging system to be loadable by the classloader that defines the implementing class. +
+
+ However, there is actually no reason why LogFactory requires symbolic references to particular Log
+ implementations. Reflection can be used to load these from an appropriate classloader
+ without unacceptable performance degradation.
+ This is the strategy adopted by JCL.
+
+ JCL uses the context classloader to use the Log implementation.
+