Author: dfabulich
Date: Thu May 1 16:29:40 2008
New Revision: 652710
URL: http://svn.apache.org/viewvc?rev=652710&view=rev
Log:
[SUREFIRE-489] Document classpath issues
Removed:
maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/forking.apt
Modified:
maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/class-loading.apt
maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml
Modified:
maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/class-loading.apt
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/class-loading.apt?rev=652710&r1=652709&r2=652710&view=diff
==============================================================================
---
maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/class-loading.apt
(original)
+++
maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/class-loading.apt
Thu May 1 16:29:40 2008
@@ -1,26 +1,112 @@
------
- Class Loading Issues
+ Classloading and Forking
------
- Brett Porter
+ Dan Fabulich
------
- July 2006
+ May 2008
------
-Class Loading Issues
+Classloading and Forking in Maven Surefire
- By default, Surefire loads classes using the default Java mechanism. However,
- it can be set to use "child first" classloading, like a web application -
- meaning your dependencies take precedence over those in the JDK. Classes in
- the java.* and javax.* packages can never be overridden. The only use for
- this is so that code in the test classpath can override stuff present in the
- JDK or its "standard extensions" directory which is not in these restricted
- packages. This means effectively implementations of the various "service
provider"
- interfaces in java such as the xml parser implementation used by jaxp,
- the cryptography providers, the socket implementation class.
+ This page discusses classloading and forking under Maven Surefire, with an eye
+ towards troubleshooting problems.
- If you find this is necessary, you can do so by setting the
<<<childDelegation>>>
- property to <<true>>:
+* Executive Summary
+ If you're having problems, you'll probably want to tinker with these three
settings: forkMode, useSystemClassLoader, and childDelegation.
+
+* What problem does Surefire solve?
+
+ Initially, the problem seems simple enough. Just launch Java with a
classpath, like this:
+
++---+
+java -classpath foo.jar:bar.jar MyApp
++---+
+
+ But there's a problem here: on some operating systems (Windows), there's a
limit on how long you can make
+ your command line, and therefore a limit on how long you can make your
classpath. The limit is different
+ on different versions of Windows; in some versions only a few hundred
characters are allowed, in others
+ a few thousand, but the limit can be pretty severe in either case.
+
+* How do people solve this problem in general?
+
+ There are two "tricks" you can use to workaround this problem; both of them
are can cause other problems in some cases.
+
+ 1. <<Isolated Classloader>>: One workaround is to use an isolated classloader.
+ Instead of launching MyApp directly, we can launch some other app (a "booter")
+ with a much shorter classpath. We can then create a new java.lang.ClassLoader
+ (usually a java.net.URLClassLoader) with your classpath configured. The booter
+ can then load up MyApp from the classloader; when MyApp refers to other
classes,
+ they will be automatically loaded from our isolated classloader.
+
+ The problem with using an isolated classloader is that your classpath isn't
+ <really> correct, and some apps can detect this and object. For example, the
+ system property "java.class.path" won't include your jars; if your app notices
+ this, it could cause a problem.
+
+ There's another similar problem with using an isolated classloader: any class
+ may call the static method ClassLoader.getSystemClassLoader() and attempt to
+ load classes out of that classloader, instead of using the default
classloader.
+ Classes often do this if they need to create classloaders of their own....
+ Unfortunately, Java-based web application servers like Jetty, Tomcat, BEA
+ WebLogic and IBM WebSphere are very likely to try to escape the confines of an
+ isolated classloader.
+
+ 2. <<Manifest-Only Jar>>: Another workaround is to use a "manifest-only jar."
In
+ this case, you create a temporary jar that's almost completely empty, except
for
+ a META-INF/MANIFEST.MF file. Java manifests can contain attributes that the
Java
+ VM will honor as directives; for example, you can have a "Class-Path"
attribute,
+ which contains a list of other jars to add to the classpath. So then you can
run
+ your code like this:
+
++---+
+java -classpath booter.jar MyApp
++---+
+
+ This is a bit more realistic, because in this case the system classloader, the
+ thread context classloader and the default classloader are all the same;
there's
+ no possibility of "escaping" the classloader. But this is still a weird
+ simulation of a "normal" classpath, and it's still possible for apps to notice
+ this. Again, java.class.path may not be what you'd expect ("why does it
contain
+ only one jar?"). Additionally, it's possible to query the system classloader
to
+ get the list of jars back out of it; your app may be confused if it finds only
+ our booter.jar there!
+
+* Advantages/Disadvantages of each solution
+
+ If your app tries to interrogate its own classloader for a list of jars, it
may
+ work better under an isolated classloader than it would with a manifest-only
+ jar. However, if your app tries to escape its default classloader, it may not
+ work under an isolated classloader at all.
+
+ One advantage of using an isolated classloader is that it's the only way to
use
+ an isolated classloader without forking a separate process, running all of the
+ tests in the same process as Maven itself. But that itself can be pretty
risky,
+ especially if Maven is running embedded in your IDE!
+
+* What does Surefire do?
+
+ Surefire provides a mechanism for using either strategy. The parameter that
+ determines this is called "useSystemClassLoader". If useSystemClassLoader is
+ true, then we use a manifest-only jar; otherwise, we use an isolated
+ classloader.
+
+ The default value for useSystemClassLoader changed between Surefire 2.3 and
+ Surefire 2.4, which was a pretty significant change. In Surefire 2.3,
+ useSystemClassLoader was false by default, and we used an isolated
classloader.
+ In Surefire 2.4, useSystemClassLoader is true by default. No value works for
+ everyone, but we think this default is an improvement; a bunch of
+ hard-to-diagnose bugs get better when we useSystemClassLoader=true.
+
+ Unfortunately, if this value is set incorrectly for your app, you're going to
+ have a problem on your hands that can be quite difficult to diagnose. You
might
+ even be forced to read a long doc page like this one. ;-)
+
+ If you're having problems when upgrading from an older version of Surefire to
a
+ newer version, try setting useSystemClassLoader=false to see if that helps.
You
+ can do that with the POM snippet below, or by setting
+ "-Dsurefire.useSystemClassLoader=false".
+
+---+
<project>
[...]
@@ -29,13 +115,24 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>2.4.2</version>
<configuration>
- <childDelegation>true</childDelegation>
+ <useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
-+---+
\ No newline at end of file
++---+
+
+* Debugging Classpath Problems
+
+ If you've read this far, you're probably fully equipped to diagnose problems
that may occur during classloading. Here's some general tips to try:
+
+ * Run mvn with --debug (aka -X) to get more detailed output
+
+ * Check your forkMode. If forkMode=never, it's impossible to use the system
classloader; we have to use an isolated classloader.
+
+ * If useSystemClassLoader=true, look at the surefire booter jar. Open it up
(it's just a zip) and read its manifest.
+
+ * Run mvn with -Dmaven.surefire.debug, and attach to the running process with
a debugger.
\ No newline at end of file
Modified: maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml
URL:
http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml?rev=652710&r1=652709&r2=652710&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml (original)
+++ maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml Thu May 1
16:29:40 2008
@@ -32,7 +32,6 @@
<item name="Inclusions and Exclusions of Tests"
href="examples/inclusion-exclusion.html"/>
<item name="Running a Single Test" href="examples/single-test.html"/>
<item name="Class Loading Issues" href="examples/class-loading.html"/>
- <item name="Forking" href="examples/forking.html"/>
<item name="Debugging Tests" href="examples/debugging.html"/>
<item name="Using System Properties"
href="examples/system-properties.html"/>
<item name="Using TestNG" href="examples/testng.html"/>