Author: markt
Date: Tue Sep 8 13:46:34 2015
New Revision: 1701805
URL: http://svn.apache.org/r1701805
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57681
Add a web application class loader implementation that supports the parallel
loading of web application classes.
Use of this feature requires a Java 7 or later JRE.
Based on a patch by Huxing Zhang.
Added:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java
(with props)
tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java
(with props)
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/LocalStrings.properties
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/mbeans-descriptors.xml
tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
tomcat/tc7.0.x/trunk/webapps/docs/config/loader.xml
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/LocalStrings.properties?rev=1701805&r1=1701804&r2=1701805&view=diff
==============================================================================
---
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/LocalStrings.properties
(original)
+++
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/LocalStrings.properties
Tue Sep 8 13:46:34 2015
@@ -66,6 +66,7 @@ webappClassLoader.addTransformer.duplica
webappClassLoader.addTransformer=Added class file transformer [{0}] to web
application [{1}].
webappClassLoader.removeTransformer=Removed class file transformer [{0}] from
web application [{1}].
webappClassLoader.transformError=Instrumentation error: could not transform
class [{0}] because its class file format is not legal.
+webappClassLoaderParallel.registrationFailed=Registration of
org.apache.catalina.loader.ParallelWebappClassLoader as capable of loading
classes in parallel failed
webappLoader.addRepository=Adding repository {0}
webappLoader.deploy=Deploying class repositories to work directory {0}
webappLoader.jarDeploy=Deploy JAR {0} to {1}
Added:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java?rev=1701805&view=auto
==============================================================================
---
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java
(added)
+++
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java
Tue Sep 8 13:46:34 2015
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.loader;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.compat.JreCompat;
+
+/**
+ * Parallel class loading implementation of WebappClassLoaderBase. Parallel
+ * class loading is only available when using a Java 7+ JRE.
+ */
+public class ParallelWebappClassLoader extends WebappClassLoaderBase {
+
+ private static final Log log =
LogFactory.getLog(ParallelWebappClassLoader.class);
+
+ static {
+ try {
+ if (JreCompat.isJre7Available()) {
+ // parallel class loading capable
+ final Method registerParallel =
+
ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ registerParallel.setAccessible(true);
+ return null;
+ }
+ });
+ Boolean result = (Boolean)registerParallel.invoke(null);
+ if (!result.booleanValue()) {
+
log.warn(sm.getString("webappClassLoaderParallel.registrationFailed"));
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+
+ public ParallelWebappClassLoader() {
+ super();
+ }
+
+
+ public ParallelWebappClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+
+ /**
+ * Returns a copy of this class loader without any class file
+ * transformers. This is a tool often used by Java Persistence API
+ * providers to inspect entity classes in the absence of any
+ * instrumentation, something that can't be guaranteed within the
+ * context of a {@link java.lang.instrument.ClassFileTransformer}'s
+ * {@link java.lang.instrument.ClassFileTransformer#transform(ClassLoader,
+ * String, Class, java.security.ProtectionDomain, byte[]) transform}
method.
+ * <p>
+ * The returned class loader's resource cache will have been cleared
+ * so that classes already instrumented will not be retained or
+ * returned.
+ *
+ * @return the transformer-free copy of this class loader.
+ */
+ @Override
+ public ParallelWebappClassLoader copyWithoutTransformers() {
+
+ ParallelWebappClassLoader result = new
ParallelWebappClassLoader(getParent());
+
+ super.copyStateWithoutTransformers(result);
+
+ try {
+ result.start();
+ } catch (LifecycleException e) {
+ throw new IllegalStateException(e);
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
Propchange:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/ParallelWebappClassLoader.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/mbeans-descriptors.xml?rev=1701805&r1=1701804&r2=1701805&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/mbeans-descriptors.xml
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/loader/mbeans-descriptors.xml
Tue Sep 8 13:46:34 2015
@@ -171,4 +171,48 @@
</mbean>
+ <mbean name="ParallelWebappClassLoader"
+ description="Classloader implementation which is specialized for
handling web applications"
+ domain="Catalina"
+ group="Loader"
+ type="org.apache.catalina.loader.ParallelWebappClassLoader">
+
+ <attribute name="className"
+ description="Fully qualified class name of the managed object"
+ type="java.lang.String"
+ writeable="false"/>
+
+ <attribute name="contextName"
+ description="Name of the webapp context"
+ type="java.lang.String"
+ writeable="false"/>
+
+ <attribute name="delegate"
+ description="The 'follow standard delegation model' flag that will
be used to configure our ClassLoader"
+ type="boolean"/>
+
+ <attribute name="antiJARLocking"
+ description="The antiJARLocking flag for this Loader"
+ type="boolean"/>
+
+ <attribute name="searchExternalFirst"
+ description="The searchExternalFirst flag for this Loader"
+ type="boolean"/>
+
+ <attribute name="stateName"
+ description="The name of the LifecycleState that this component is
currently in"
+ type="java.lang.String"
+ writeable="false"/>
+
+ <attribute name="URLs"
+ description="The URLs of this loader"
+ type="[Ljava.net.URL;"/>
+
+ <attribute name="jarPath"
+ description="The jarPath of this loader"
+ writeable="false"
+ type="java.lang.String"/>
+
+ </mbean>
+
</mbeans-descriptors>
Added:
tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java?rev=1701805&view=auto
==============================================================================
---
tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java
(added)
+++
tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java
Tue Sep 8 13:46:34 2015
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.loader;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.compat.JreCompat;
+
+public class TestParallelWebappClassLoader extends TomcatBaseTest {
+
+ private static final String PARALLEL_CLASSLOADER =
+ "org.apache.catalina.loader.ParallelWebappClassLoader";
+ private static final String DUMMY_SERVLET =
+ "org.apache.catalina.loader.DummyServlet";
+
+ @Test
+ public void testParallelCapableOnJre7() {
+ if (!JreCompat.isJre7Available()) {
+ // ignore on Jre6 or lower
+ return;
+ }
+ try {
+ Tomcat tomcat = getTomcatInstance();
+ Context ctx = tomcat.addContext("", null);
+
+ WebappLoader webappLoader = new WebappLoader();
+ webappLoader.setLoaderClass(PARALLEL_CLASSLOADER);
+ ctx.setLoader(webappLoader);
+
+ tomcat.start();
+
+ ClassLoader classloader = ctx.getLoader().getClassLoader();
+
+ Assert.assertTrue(classloader instanceof
ParallelWebappClassLoader);
+
+ // parallel class loading capable
+ Method getClassLoadingLock =
+ getDeclaredMethod(classloader.getClass(),
"getClassLoadingLock", String.class);
+ // make sure we have getClassLoadingLock on JRE7.
+ Assert.assertNotNull(getClassLoadingLock);
+ // give us permission to access protected method
+ getClassLoadingLock.setAccessible(true);
+
+ Object lock = getClassLoadingLock.invoke(classloader,
DUMMY_SERVLET);
+ // make sure it is not a ParallelWebappClassLoader object lock
+ Assert.assertNotEquals(lock, classloader);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail("testParallelCapableOnJre7 fails.");
+ }
+ }
+
+ @Test
+ public void testParallelIncapableOnJre6() {
+ if (JreCompat.isJre7Available()) {
+ // ignore on Jre7 or above
+ return;
+ }
+ try {
+ Tomcat tomcat = getTomcatInstance();
+ // Must have a real docBase - just use temp
+ Context ctx = tomcat.addContext("",
+ System.getProperty("java.io.tmpdir"));
+
+ WebappLoader webappLoader = new WebappLoader();
+ webappLoader.setLoaderClass(PARALLEL_CLASSLOADER);
+ ctx.setLoader(webappLoader);
+
+ tomcat.start();
+
+ ClassLoader classloader = ctx.getLoader().getClassLoader();
+
+ Assert.assertTrue(classloader instanceof
ParallelWebappClassLoader);
+
+ // parallel class loading capable
+ Method getClassLoadingLock =
+ getDeclaredMethod(classloader.getClass(),
"getClassLoadingLock", String.class);
+ // make sure we don't have getClassLoadingLock on JRE6.
+ Assert.assertNull(getClassLoadingLock);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail("testParallelIncapableOnJre6 fails.");
+ }
+ }
+
+ private Method getDeclaredMethod(Class<?> clazz, String name, Class<?>...
parameterTypes) {
+ if (clazz == null) return null;
+ for (Method method: clazz.getDeclaredMethods()) {
+ if (method.getName().equals(name)) {
+ return method;
+ }
+ }
+ // find from super class
+ return getDeclaredMethod(clazz.getSuperclass(), name, parameterTypes);
+ }
+
+ @SuppressWarnings("unused")
+ private static final class DummyServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ // do nothing
+ }
+ }
+}
\ No newline at end of file
Propchange:
tomcat/tc7.0.x/trunk/test/org/apache/catalina/loader/TestParallelWebappClassLoader.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1701805&r1=1701804&r2=1701805&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Tue Sep 8 13:46:34 2015
@@ -60,6 +60,12 @@
<section name="Tomcat 7.0.65 (violetagg)">
<subsection name="Catalina">
<changelog>
+ <add>
+ <bug>57681</bug>: Add a web application class loader implementation
that
+ supports the parallel loading of web application classes. Use of this
+ feature requires a Java 7 or later JRE. Based on a patch by Huxing
+ Zhang. (markt)
+ </add>
<fix>
<bug>58187</bug>: Correct a regression in the fix for <bug>57765</bug>
that meant that deployment of web applications deployed via the Manager
Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/loader.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/loader.xml?rev=1701805&r1=1701804&r2=1701805&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/loader.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/loader.xml Tue Sep 8 13:46:34 2015
@@ -125,7 +125,11 @@
implementation class to use. If not specified, the default value is
<code>org.apache.catalina.loader.WebappClassLoader</code>. Custom
<strong>loaderClass</strong> implementations must extend
- <code>org.apache.catalina.loader.WebappClassLoaderBase</code>.</p>
+ <code>org.apache.catalina.loader.WebappClassLoaderBase</code>.The
+ default <strong>loaderClass</strong> is not parallel capable. A
parallel
+ capable <strong>loaderClass</strong> is available when running on a
Java
+ 7 or higher JRE and can be used by specifying
+ <code>org.apache.catalina.loader.ParallelWebappClassLoader</code>.</p>
</attribute>
<attribute name="searchExternalFirst" required="false">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]