ClassLoader-A

Download Report

Transcript ClassLoader-A

ClassLoading
Survival Guide
Peter Keavney
Andrea O. K. Wright
Chariot Solutions
www.chariotsolutions.com
1
| 2004 JavaOneSM Conference | BOF-2519
java.sun.com/javaone/sf
ClassLoading Survival Guide
Understanding Java ClassLoading
With an understanding of how ClassLoading
works, you will be able to debug and avoid
common pitfalls.
We will not only look at ways to prevent
ClassLoading from breaking an application,
we will also talk about how applications may
be enhanced with custom ClassLoaders.
2
| 2004 JavaOneSM Conference | BOF-2509
Agenda
ClassLoading Basics
ClassLoading in the J2EE 1.3 and 1.4
Specs
App Server ClassLoading Policies
Diagnosing Common ClassLoading
Problems
Enhancing Applications with Techniques
Involving ClassLoaders
3
| 2004 JavaOneSM Conference | BOF-2509
Java ClassLoading Basics
• What is a class loader?
– mechanism for loading
classes into the JVM
– subclass of
java.lang.ClassLoader
• Hierarchical structure
– Parent-child
relationships
• Uses delegation
– Load requests
delegated to parent
4
| 2004 JavaOneSM Conference | BOF-2509
ClassLoader-A
Class-X
ClassLoader-B
Class-Y
Class-Z
ClassLoader-C
Class-Z
Java ClassLoading Basics
• Unidirectional visibility
– Parent-loaded classes cannot
see child-loaded classes
– Thread.getContextClassloader()
ClassLoader-A
Class-X
• Unique Namespaces
– Classes referenced as
classloader.classname
ClassLoader-B
Class-Y
Class-Z
ClassLoader-C
Class-R
Class-D
• Variety of class file locations
– File system
– Databases
– Remote server locations
File system
Database
Remote
Server
5
| 2004 JavaOneSM Conference | BOF-2509
Java ClassLoading Basics
• Bootstrap ClassLoader
─ aka Primordial ClassLoader
─ Created by the JVM
─ Loads the JDK classes included
in the JVM
(including
java.lang.ClassLoader)
Bootstrap ClassLoader
• Extensions ClassLoader
─ Loads JRE classes
• System ClassLoader
─ loads classes specified in the
classpath
─ Loads applications, shared
libraries, jars, etc.
6
| 2004 JavaOneSM Conference | BOF-2509
Extensions ClassLoader
System ClassLoader
Application
JAR
Shared Lib
Java ClassLoading Basics
Typical Loading Scenario
Determine Initial ClassLoader
Bootstrap ClassLoader
Extension ClassLoader
Delegate to Parent ClassLoader
System ClassLoader
Class Loaded?
No – Delegate to Parent
Lastly – If class is not loaded in
parent hierarchy then the Initial
loader will attempt to load the
class itself.
7
| 2004 JavaOneSM Conference | BOF-2509
Class Loader A
Class Loader B
Class Loader C
MyClass
Agenda
ClassLoading Basics
ClassLoading in the J2EE 1.3 and 1.4
Specs
App Server ClassLoading Policies
Diagnosing Common ClassLoading
Problems
Enhancing Applications with Techniques
Involving ClassLoaders
8
| 2004 JavaOneSM Conference | BOF-2509
J2EE Specification Requirements
• J2EE v1.3 – section 8.1.1.2 mandates application servers must load
dependent JAR files listed in the Manifest Class-Path entry of a
primary JAR file (typically an EJB JAR). This requirement is not
mandated for EAR or WAR files.
• J2EE v1.4 – section 8.3.1 states the following:
– Classes loaded by lower-level class loaders must be able to
discover the top-level application class loader used to
dynamically load application classes.
– Applications, deployed as archives, must ensure that the Java
classes in the application are in a separate namespace from
classes in other Java applications.
• J2EE containers must provide a context class loader per thread that
can be used to load top-level application classes.
9
| 2004 JavaOneSM Conference | BOF-2509
Agenda
ClassLoading Basics
ClassLoading in the J2EE 1.3 and 1.4
Specs
App Server ClassLoading Policies
Diagnosing Common ClassLoading
Problems
Enhancing Applications with Techniques
Involving ClassLoaders
10
| 2004 JavaOneSM Conference | BOF-2509
WebLogic
• System ClassLoader
– Loads WebLogic Server
classes
– Loads deployed applications
– Loads resources shared
across applications
Bootstrap ClassLoader
Extension ClassLoader
System ClassLoader
• Individual Applications
– Load EJB JARs
– Load resources shared
within application
– Load Web Applications
EAR
RAR
EJB
JAR
• Web Applications
– Load servlets, JSPs, etc
11
| 2004 JavaOneSM Conference | BOF-2509
JAR
WAR
EJB
JAR
EJB
JAR
WAR
WebSphere
• WebSphere ClassLoader
– Loads WebSphere run-time
– Loads required J2EE classes
Bootstrap ClassLoader
Extension ClassLoader
• Application Extensions
ClassLoader
– Loads application(s) into a
single namespace when Policy
is set to SINGLE
• Module ClassLoader
– Loads Web Applications when
Isolation Policy set to Module
12
| 2004 JavaOneSM Conference | BOF-2509
System ClassLoader
WebSphere ClassLoader
Application Ext ClassLoader
Module ClassLoader
EAR
WAR
WAR
Oracle iAS
• System ClassLoader
– Loads OC4J System Classes
• Global Connectors
ClassLoader
– Loads connectors resources
shared across applications
Bootstrap ClassLoader
Extension ClassLoader
System ClassLoader
Global Connectors ClassLoader
Global Applications ClassLoader
• Global Applications
ClassLoader
EAR
EAR
– Loads applications
EAR
13
| 2004 JavaOneSM Conference | BOF-2509
EAR
JBoss
• UnifiedClassLoader3
– Extends java.net.URLClassLoader
– Loads classes and resources into
UnifiedLoaderRepository3
overriding the standard parent
delegation model.
• UnifiedLoaderRepository3
– Registers Multiple
UnifiedClassLoaders
Bootstrap ClassLoader
Extensions ClassLoader
System ClassLoader
UnifiedClassLoader3
UnifiedClassLoader3
UnifiedClassLoader3
Unified
Loader
Repository3
EAR
EAR
14
| 2004 JavaOneSM Conference | BOF-2509
EJB
EAR WAR
JAR
WebLogic
Oracle iAS
System ClassLoader
System ClassLoader
EAR
JAR
Global Connectors ClassLoader
WAR
Global Applications ClassLoader
RAR
EAR
EAR
EJB
JAR
EJB
JAR
EAR
WAR
System ClassLoader
System ClassLoader
WebSphere ClassLoader
UnifiedClassLoader3
UnifiedClassLoader3
UnifiedClassLoader3
Application Ext ClassLoader
Module ClassLoader
EAR
Unified
Loader
Repository
WAR
WebSphere
15
EAR
| 2004 JavaOneSM Conference | BOF-2509
JBoss
Server Configuration
Application Isolation
Delegation Control
Control
WebLogic
WebSphere
Oracle iAS
JBoss
Placing modules in the App-Inf\lib directory
enables sharing between them.
Setting PreferWebInf to “true” subverts
normal hierarchy delegation
Setting ClassLoader Policy to SINGLE will
load all applications from a single
ClassLoader. Setting Policy to MULTIPLE
gives each app it’s own ClassLoader.
Setting Application Mode to PARENT_FIRST is
the default behavior
Specifying <Application parent=“X”> allows
cross application sharing of “X”s children.
<web-app-class-loader search-local- classesfirst=“true”> subverts normal delegation for
Web Applications.
<class-loading>
<loader-repository>
<loader-repository>
dot.com:loader=archive
</loader-repository>
</class-loading>
Setting mode to PARENT_LAST subverts
normal delegation.
dot.com:loader=-archive
<loader-repository-config>
Java2ParentDelegaton=false
</loader-repository-config>
</loader-repository>
16
| 2004 JavaOneSM Conference | BOF-2509
Agenda
ClassLoading Basics
ClassLoading in the J2EE 1.3 and 1.4
Specs
App Server ClassLoading Policies
Diagnosing Common ClassLoading
Problems
Enhancing Applications with Techniques
Involving ClassLoaders
17
| 2004 JavaOneSM Conference | BOF-2509
The Class Could Not Be Found
EJB.JAR
18
| 2004 JavaOneSM Conference | BOF-2509
STRUTS.JAR
WAR A
WAR B
AppAForm
AppBForm
The Class Could Not Be Found
• ClassNotFoundException
─ Used String representation (e.g.
ClassLoader.LoadClass(className))
─ Typically, dependent Class is only visible to children
• NoClassDefFoundError
─ Class existed at compile time
─ Typically, dependent Class is only visible to children
• NoClassDefFoundException
─ An interesting phenomenon: this Exception is not in
the JDK, but it appears in dozens of topics in
developer forums 
19
| 2004 JavaOneSM Conference | BOF-2509
The Same Class Was Loaded By
Multiple ClassLoaders
EJB
JAR
public void utilityMethod (Object o) {
((Apple)o).doSomething();
}
CLASSCASTEXCEPTION
Apple
20
| 2004 JavaOneSM Conference | BOF-2509
WAR A
WAR B
Apple
Apple
The Same Class Was Loaded By
Multiple ClassLoaders
• ClassCastException
─This is usually a bug 
─But sometimes… same Class was loaded by
two different ClassLoaders
• ClassCircularityError
─A Class and one of its dependents are both
dependent on a third Class; different
ClassLoaders are used to load that third
Class
21
| 2004 JavaOneSM Conference | BOF-2509
Diagnostic Statements
•
•
•
•
Class.getClassLoader()
System.getSystemClassLoader()
Thread.currentThread.getContextClassLoader()
ClassLoader.getParent()
• Class.getProtectionDomain().getCodeSource().
getLocation()
• URLClassLoader.getURLs()
• Printing out the contents of a JAR:
JarEntry jarEntry;
Jar InputStream jarInputStream = new
JarInputStream(urls[i].openConnection().getInputStream());
while((jarEntry=jarInputStream.getNextJarEntry())!=null) {
System.out.println(jarEntry.getName());
}
22
| 2004 JavaOneSM Conference | BOF-2509
Getting Diagnostic Information
• Use the -verbose option
• Place diagnostic statements in the application
code
• Place diagnostic statements in a custom
ClassLoader
• Place diagnostic statements in the core Java
ClassLoaders. The -Xbootclasspath option
makes to possible to supersede core Classes
in a development environment.
C:\>java -Xbootclasspath:C:\debug;j2sdk1.4.2_03\jre\lib\rt.jar
…[all other boot.class.path jars] app.java
23
| 2004 JavaOneSM Conference | BOF-2509
Sample App for Debugging
TopHat.java
import
import
import
import
import
java.io.File;
java.net.MalformedURLException;
java.net.URLClassLoader;
java.net.URL;
demo.Rabbit;
/**
* Instantiates and displays a Rabbit.
*/
public class TopHat {
public static void main (String args[]) {
try {
// Create a ClassLoader that knows where to find demo.Rabbit
URL rabbitURL = new File("rabbit.jar").toURL();
URL[] urls = new URL[]{rabbitURL};
URLClassLoader rabbitClassLoader = new URLClassLoader(urls,Thread.currentThread().getContextClassLoader());
// Set the ContextClassLoader for the current Thread so that it can find Rabbit.class
Thread.currentThread().setContextClassLoader(rabbitClassLoader);
// Make a Rabbit appear.
System.out.println(new Rabbit());
} catch (MalformedURLException malformedURLException) {
malformedURLException.printStackTrace();
}
}
}
24
| 2004 JavaOneSM Conference | BOF-2509
Compile Time and Runtime Environments
Rabbit.java
package demo;
public class Rabbit {
}
rabbit.jar
C:\> jar tf rabbit.jar
demo/
demo.Rabbit.class
Compilation
C:\> javac –classpath rabbit.jar TopHat.java
Command Line
C:\> java TopHat
25
| 2004 JavaOneSM Conference | BOF-2509
Desired Behavior vs. Actual Behavior
Desired Behavior
Tophat should instantiate and display a String
representation of a Rabbit, even though
rabbit.jar is not referenced on the application
classpath.
Actual Behavior
C:\>java TopHat
Exception in thread "main" java.lang.NoClassDefFoundError:
demo/Rabbit
at TopHat.main(TopHat.java:23)
26
| 2004 JavaOneSM Conference | BOF-2509
TopHat.java with Diagnostic Statements
// Create a ClassLoader that knows where to find demo. Rabbit
URL rabbitURL = new File("rabbit.jar").toURL();
URL[] urls = new URL[]{rabbitURL};
URLClassLoader rabbitClassLoader = new
URLClassLoader(urls,Thread.currentThread().getContextClassLoader());
System.out.println("---> ClassLoader for TopHat: " +
TopHat.class.getClassLoader());
System.out.println("---> Before setting a custom ContextClassLoader,
ContextClassLoader is: “);
System.out.println( Thread.currentThread().getContextClassLoader());
// Set the ContextClassLoader for the current Thread so that it can find
// Rabbit
Thread.currentThread().setContextClassLoader(rabbitClassLoader);
System.out.println("---> After setting a custom ContextClassLoader
ContextClassLoader is: ");
System.out.println( Thread.currentThread().getContextClassLoader());
// Make a Rabbit appear.
System.out.println(new Rabbit());
27
| 2004 JavaOneSM Conference | BOF-2509
Output From Diagnostics in the
Application
C:\>java TopHat
---> ClassLoader for TopHat:
sun.misc.Launcher$AppClassLoader@e80a59
---> Before setting a custom ContextClassLoader,
ContextClassLoader is:
sun.misc.Launcher$AppClassLoader@e80a59
---> After setting a custom ContextClassLoader,
ContextClassLoader is:
java.net.URLClassLoader@eee36c
Exception in thread "main"
java.lang.NoClassDefFoundError: demo/Rabbit
at TopHat.main(TopHat.java:28)
28
| 2004 JavaOneSM Conference | BOF-2509
Diagnostics in java.net.URLClassLoader
protected Class findClass(final String name) throws ClassNotFoundException {
try {
return (Class)
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
System.out.println(“-- Looked in:”);
URL[] urls = getURLs();
for (int i = 0;i<urls.length;i++) {
System.out.println(urls[i]);
}
throw new ClassNotFoundException(name);
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
}
29
| 2004 JavaOneSM Conference | BOF-2509
Diagnostics in java.lang.ClassLoader
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class c = findLoadedClass(name);
if (c == null) {
try {
if (name.equals("demo.Rabbit"))
System.out.println("---> " + this + "is asking parent (" + parent + ") to try to load " +
name + ".");
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then call findClass in order
// to find the class.
if (name.equals("demo.Rabbit"))
System.out.println("---> " + name + " was not found by parent (" + parent + "), so " + this +
" will try.");
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
void addClass(Class c) {
if (c.toString().equals("class demo.Rabbit"))
System.out.println("---> " + this + "loaded "
+ c);
classes.addElement(c);
}
30
| 2004 JavaOneSM Conference | BOF-2509
private synchronized Class loadClassInternal(String
name)throws ClassNotFoundException {
if (name.equals("demo.Rabbit")) {
System.out.println("JVM is requesting that " +
this +" load "+ name); }
return loadClass(name);
}
Output from Diagnostics in the
Core Java Classes
---> JVM is requesting that sun.misc.Launcher$AppClassLoader@e80a59 load demo.Rabbit
---> sun.misc.Launcher$AppClassLoader@e80a59 is asking parent (sun.misc.Launcher$
ExtClassLoader@1ff5ea7) to try to load demo.Rabbit.
---> sun.misc.Launcher$ExtClassLoader@1ff5ea7 is asking parent (null) to try to load
demo.Rabbit.
---> demo.Rabbit was not found by parent (null), so
sun.misc.Launcher$ExtClassLoader@1ff5ea7 will try.
--> Looked in:
file:/C:/j2sdk1.4.2_03/jre/lib/ext/dnsns.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/ldapsec.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/localedata.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/sunjce_provider.jar
---> demo.Rabbit was not found by parent (sun.misc.Launcher$ExtClassLoader@1ff5ea7), so
sun.misc.Launcher$AppClassLoader@e80a59 will try.
--> Looked in:
file:/C:/
Exception in thread "main" java.lang.NoClassDefFoundError: demo/Rabbit
at TopHat.main(TopHat.java:28)
31
| 2004 JavaOneSM Conference | BOF-2509
Analysis
• Regardless of how the Context ClassLoader
is set, the classloader that loaded the calling
Class will always be used to load a requested
Class when no ClassLoader is specified
– new ClassName()
– Class.forName(“package.ClassName”)
• Context ClassLoaders are used by
– JNDI
– JAXP
32
| 2004 JavaOneSM Conference | BOF-2509
Possible Solutions
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
loader.loadClass(“demo.Rabbit”).newInstance();
– or –
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
Class.forName(“demo.Rabbit”,
loader).newInstance();
33
| 2004 JavaOneSM Conference | BOF-2509
Rabbit Appears
---> java.net.URLClassLoader@defa1a is asking parent (sun.misc.Launcher$AppClassL
oader@e80a59) to try to load demo.Rabbit.
---> sun.misc.Launcher$AppClassLoader@e80a59 is asking parent (sun.misc.Launcher$
ExtClassLoader@1ff5ea7) to try to load demo.Rabbit.
---> sun.misc.Launcher$ExtClassLoader@1ff5ea7 is asking parent (null) to try to
load demo.Rabbit.
---> demo.Rabbit was not found by parent (null), so sun.misc.Launcher$ExtClassLo
ader@1ff5ea7 will try.
--> Looked in:
file:/C:/j2sdk1.4.2_03/jre/lib/ext/dnsns.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/ldapsec.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/localedata.jar
file:/C:/j2sdk1.4.2_03/jre/lib/ext/sunjce_provider.jar
---> demo.Rabbit was not found by parent (sun.misc.Launcher$ExtClassLoader@1ff5e
a7), so sun.misc.Launcher$AppClassLoader@e80a59 will try.
--> Looked in:
file:/C:/
---> demo.Rabbit was not found by parent (sun.misc.Launcher$AppClassLoader@e80a5
9), so java.net.URLClassLoader@defa1a will try.
---> java.net.URLClassLoader@defa1a loaded class demo.Rabbit
demo.Rabbit@a18aa2
34
| 2004 JavaOneSM Conference | BOF-2509
Sample Web App for Debugging
Rabbit.java
package webdemo;
public class Rabbit {
public static boolean visible = true;
}
manifest.mf
Manifest-Version: 1.0
Class-Path: rabbit.jar
C:\>jar
tf thinair.war
META-INF/
META-INF/MANIFEST.MF
thinair.jsp
C:\slides5>jar tf magic.ear
META-INF/
META-INF/application.xml
rabbit.jar
thinair.war
tophat.war
35
| 2004 JavaOneSM Conference | BOF-2509
C:\>jar tf tophat.war
META-INF/
META-INF/MANIFEST.MF
tophat.jsp
thinair.jsp
<%@ page import=“webdemo.Rabbit" %>
<HTML>
<BODY>
<%
if (Rabbit.visible)
%>
<pre>
^
^
/ |
/ |
/ ^| / ^|
\ ^/ \ ^/
\/ -- \/
/
\
| 6
6 |
\
=@= /
\
o /
/
\
</pre>
<%
Rabbit.visible = !Rabbit.visible;
%>
</BODY>
</HTML>
36
| 2004 JavaOneSM Conference | BOF-2509
tophat.jsp
<%@ page import=“webdemo.Rabbit" %>
<HTML>
<BODY>
<%
if (Rabbit.visible)
%>
<pre>
^
^
/ |
/ |
/ ^| / ^|
\ ^/ \ ^/
\/ -- \/
/
\
| 6
6 |
\
=@= /
\
o /
/
\
</pre>
<%
else
for (int i = 0; i < 9; i++) {
%>
<BR>
<%
}
Rabbit.visible = !Rabbit.visible;
%>
<pre>
===================
|MWMWMWMWMW|
|MWMWMWMWMW|
|MWMWMWMWMW|
|MWMWMWMWMW|
|MWMWMWMWMW|
|MWMWMWMWMM|
</pre>
</BODY>
</HTML>
37
| 2004 JavaOneSM Conference | BOF-2509
38
| 2004 JavaOneSM Conference | BOF-2509
39
| 2004 JavaOneSM Conference | BOF-2509
40
| 2004 JavaOneSM Conference | BOF-2509
41
| 2004 JavaOneSM Conference | BOF-2509
42
| 2004 JavaOneSM Conference | BOF-2509
The –verbose Option
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
[Loaded
43
jsp_servlet.__thinair]
jsp_servlet.__thinair]
weblogic.utils.http.QueryParams]
javax.servlet.jsp.JspWriter]
javax.servlet.jsp.tagext.BodyContent]
weblogic.servlet.jsp.ByteWriter]
weblogic.servlet.jsp.BodyContentImpl]
weblogic.servlet.jsp.JspWriterImpl]
weblogic.servlet.internal.DelegateChunkWriter]
weblogic.utils.UnsyncHashtable]
weblogic.utils.UnsyncHTEntry]
javax.ejb.Handle]
weblogic.servlet.internal.session.FileSessionData]
javax.servlet.http.Cookie]
weblogic.servlet.internal.ChunkUtils]
demo.Rabbit]
weblogic.servlet.internal.CookieParser]
weblogic.servlet.logging.FormatStringBuffer]
weblogic.servlet.internal.InetAddressCacheRecord]
weblogic.utils.concurrent.Lock]
weblogic.utils.concurrent.Mutex]
jsp_servlet.__tophat]
jsp_servlet.__tophat]
demo.Rabbit]
weblogic.drs.internal.HeartbeatMessage]
| 2004 JavaOneSM Conference | BOF-2509
Diagnostics in Core ClassLoaders
---> demo.Rabbit was not found by parent (sun.misc.Launcher$AppClassLoader@f38798), so
weblogic.utils.classloaders.GenericClassLoader@6b51d8 finder:
weblogic.utils.classloaders.MultiClassFinder@a2c691 annotation: will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@6b51d8 finder:
weblogic.utils.classloaders.MultiClassFinder@a2c691 annotation: ), so
weblogic.utils.classloaders.GenericClassLoader@6d4f30 finder:
weblogic.utils.classloaders.MultiClassFinder@bf9839 annotation: ApplicationClassLoader@ will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@6d4f30 finder:
weblogic.utils.classloaders.MultiClassFinder@bf9839 annotation: ApplicationClassLoader@), so
weblogic.utils.classloaders.GenericClassLoader@7227a8 finder:
weblogic.utils.classloaders.MultiClassFinder@98c92c annotation: magic@ will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@7227a8 finder:
weblogic.utils.classloaders.MultiClassFinder@98c92c annotation: magic@), so
weblogic.utils.classloaders.ChangeAwareClassLoader@899e6a finder:
weblogic.utils.classloaders.MultiClassFinder@1444b03 annotation: magic@thinair will try.
---> weblogic.utils.classloaders.ChangeAwareClassLoader@899e6a finder:
weblogic.utils.classloaders.MultiClassFinder@1444b03 annotation: magic@thinair loaded class demo.Rabbit
---> demo.Rabbit was not found by parent (sun.misc.Launcher$AppClassLoader@f38798), so
weblogic.utils.classloaders.GenericClassLoader@6b51d8 finder:
weblogic.utils.classloaders.MultiClassFinder@a2c691 annotation: will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@6b51d8 finder:
weblogic.utils.classloaders.MultiClassFinder@a2c691 annotation: ), so
weblogic.utils.classloaders.GenericClassLoader@6d4f30 finder:
weblogic.utils.classloaders.MultiClassFinder@bf9839 annotation: ApplicationClassLoader@ will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@6d4f30 finder:
weblogic.utils.classloaders.MultiClassFinder@bf9839 annotation: ApplicationClassLoader@), so
weblogic.utils.classloaders.GenericClassLoader@7227a8 finder:
weblogic.utils.classloaders.MultiClassFinder@98c92c annotation: magic@ will try.
---> demo.Rabbit was not found by parent (weblogic.utils.classloaders.GenericClassLoader@7227a8 finder:
weblogic.utils.classloaders.MultiClassFinder@98c92c annotation: magic@), so
weblogic.utils.classloaders.ChangeAwareClassLoader@cdf872 finder:
weblogic.utils.classloaders.MultiClassFinder@7d0e5e annotation: magic@tophat will try.
---> weblogic.utils.classloaders.ChangeAwareClassLoader@cdf872 finder:
weblogic.utils.classloaders.MultiClassFinder@7d0e5e annotation: magic@tophat loaded classdemo.Rabbit
44
| 2004 JavaOneSM Conference | BOF-2509
Possible Solutions
• J2EE spec does not provide ClassLoading
guidelines for Classes specified using the
class-path tag in a web app’s manifest
─WebLogic uses the web app’s ClassLoader
• Server classpath
─Downside: Server needs to be restarted
whenever a library class changes
• Use vendor-specific means of specifying a
ClassLoader hierarchy.
─Downside: Complicates porting to another
server
45
| 2004 JavaOneSM Conference | BOF-2509
Agenda
ClassLoading Basics
ClassLoading in the J2EE 1.3 and 1.4
Specs
App Server ClassLoading Policies
Diagnosing Common ClassLoading
Problems
Enhancing Applications with Techniques
Involving ClassLoaders
46
| 2004 JavaOneSM Conference | BOF-2509
Enhancing Applications with Techniques
Involving ClassLoaders
• Customizing Security
• Improving Performance
• Providing Flexibility
47
| 2004 JavaOneSM Conference | BOF-2509
Modifying the Default Security Policy
Using a Custom ClassLoader
Default Permissions Checking:
• When a permissions check is requested, policy
configuration files are consulted.
• Permissions may be granted based on user and/or
codebase
• Sample policy file entries:
grant principal "Max" {
permission demo.PrintBackStagePassesPermission;
};
grant codeBase “http://honorable.com" {
permission java.io.FilePermission "C:\\secrets\*", "read"
};
48
| 2004 JavaOneSM Conference | BOF-2509
Augmenting Permissions
Granted By the Default Mechanism
• Extend URLClassLoader to override
getPermissions(CodeSource codesource)
• Call super.getPermissions(codesource)
─ Adds FilePermissions or ConnectionPermissions based on the
location of the Class and the URL protocol
• Authorization information may be obtained from the database
• Permissions may be role-based
protected PermissionCollection getPermissions(CodeSource
cs){
PermissionsCollection pc = super.getPermissions(cs);
if (checkRoles(username,"Magician's Assistant")) {
pc.add(new demo.PrintBackStagePassesPermission());
}
return pc;
}
49
| 2004 JavaOneSM Conference | BOF-2509
A Custom ClassLoader that Helps
Protect Against Decompilation
• Encrypt Classes before deployment
• Extend URLClassLoader, and override findClass to decrypt the
class before calling defineClass
• If the encrypted Classes are delegated to the System
ClassLoader, it will throw an Exception, so either…
─ ensure that the encrypted Classes are not on the classpath
─ or override loadClass so that only core Classes are
delegated to the System loader
• Caveat
─ Class data must eventually pass through the final
java.lang.ClassLoader defineClass()
─ Using the -Xbootclasspath option we looked at earlier, a
modified java.lang.ClassLoader could be installed. It's
definition of defineClass could be modified to send the
decrypted data to a file!
50
| 2004 JavaOneSM Conference | BOF-2509
Enhancing Applications with Techniques
Involving ClassLoaders
• Customizing Security
• Improving Performance
• Providing Flexibility
51
| 2004 JavaOneSM Conference | BOF-2509
Ensure that initialization-intensive
Classes are not loaded until needed
• All Classes will be loaded when the enclosing Class is loaded:
Screen currentScreen;
String command = actionEvent.getCommand();
if (command.equals(PULL_RABBIT_OUT_OF_HAT)) {
currentScreen = new RabbitOutOfHatScreen();
} else if (command.equals(ESCAPE_FROM_LOCKED_TRUNK)) {
currentScreen = new EscapeFromLockedTrunkScreen();
} else if (command.equals(DISAPPEAR_IN_THIN_AIR))
currentScreen = new DisappearInThinAirScreen();
} else …
• Classes will be loaded on an as-needed basis:
String command = actionEvent.getCommand();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String className = “demo.” + command + “Screen”;
currentScreen = (Screen) loader.loadClass(className).newInstance();
52
| 2004 JavaOneSM Conference | BOF-2509
Controlling Applet ClassLoading
• If all the Applet classes are in a single JAR,
startup may be unacceptably slow
• Create a URL ClassLoader to load additional
classes on an as-needed basis
─ Warning: Using new to invoke the
URLClassLoader will yield a security
Exception
─ Even an unsigned applet can use
URLClassLoader.newInstance(URL[]
urls,ClassLoader parent) to set the
URLs for a URLClassLoader
53
| 2004 JavaOneSM Conference | BOF-2509
Controlling Applet ClassLoading, Cnt’d
• The Screens classes will be loaded on an as-needed basis.
Screen currentScreen;
String command = actionEvent.getCommand();
URLClassLoader loader =
URLClassLoader.newInstance(new URL[]{new URL("file:///C:/screens")},
getClass().getClassLoader());
String className = command + “Screen”;
currentScreen = (Screen) loader.loadClass(className).newInstance();
• The Screens are not in magicshow.jar; they are not referenced
the applet element.
<h1>Magic Show Applet<h1>
<applet code=MagicShow.class archive=magicshow.jar width=500
height=500>
</applet>
54
| 2004 JavaOneSM Conference | BOF-2509
Enhancing Applications with Techniques
Involving ClassLoaders
• Customizing Security
• Improving Performance
• Providing Flexibility
55
| 2004 JavaOneSM Conference | BOF-2509
Pluggable, Hot-deployable Modules
• Once a Class is Loaded by a ClassLoader, it cannot be
reloaded by that ClassLoader, so a new ClassLoader
must be instantiated to load a new version of a Class.*
• Classes cannot be hot deployed by the System
ClassLoader
– Ensure that hot-deployable Classes are not on the
classpath
A Pluggable “Volunteer from the Audience”
URLClassLoader loader;
protected Volunteer getVolunteer(String volunteerName) {
//When a class loader is axed, all the classes it loaded are discarded
URL[] pluginPaths = new URL[]{new URL(“AnyDirectoryNotOnClasspath”)};
loader = new URLClassLoader(pluginPaths, getClass.getClassLoader());
return (Volunteer)loader.loadClass(volunteerName, true);
}
56
| 2004 JavaOneSM Conference | BOF-2509
Other Cool Uses for Custom
ClassLoaders
• A ClassLoader that accepts a version number,
checks out the code from CVS, and loads
Classes from the target build directory
─ A New Era for Java Protocol Handlers by Brian Maso
(http://java.sun.com/developer/onlineTraining/protocolhandlers/)
• A ClassLoader that constructs a JAR that only
contains Classes that were actually used by the
program
─ Minimize Java Distributions with an Automated,
Custom JAR File by Greg Travis
(http://www.devx.com/Java/Article/1767)
• A ClassLoader that knows how to apply patches
─ Clinton S. Bennion, Principal Software Engineer,
Brooks Automation
57
| 2004 JavaOneSM Conference | BOF-2509
References
•
Classloading in Oracle9iAS Containers for J2EE
─ Bryan Atsatt and Debu Panda
•
Understanding Class.forName
─ Ted Neward
•
Making the most of WebLogic Classloaders
─ John Musser
•
J2EE Class Loading Demystified
─ Tim deBoer and Gary Karasiuk
•
J2EE Design and Development
─ Rod Johnson
•
The Class Loading Architecture of JBoss 3.0.7 and 3.2
─ The Jboss Group, LLC
•
Advanced Classloading in J2EE
─ David Bosschaert and Arne Koschel
•
Find a way out of the ClassLoader maze
─ Vladimir Roubtsov
58
| 2004 JavaOneSM Conference | BOF-2509
Q&A
Peter Keavney
Andrea O. K. Wright
Chariot Solutions
59
| 2004 JavaOneSM Conference | Session XXXX