diff options
author | Jan Bartel | 2012-08-09 00:23:00 +0000 |
---|---|---|
committer | Jan Bartel | 2012-08-09 00:23:00 +0000 |
commit | 0b4d2e6a0fe6b37363ee0caf7f84b420b7c74cc2 (patch) | |
tree | e44f6b79626ee168b7a3b4f27f6d052aaed5d913 | |
parent | b2fd3aad26de8f784253bd07c9cd5652513cbb9c (diff) | |
download | org.eclipse.jetty.project-0b4d2e6a0fe6b37363ee0caf7f84b420b7c74cc2.tar.gz org.eclipse.jetty.project-0b4d2e6a0fe6b37363ee0caf7f84b420b7c74cc2.tar.xz org.eclipse.jetty.project-0b4d2e6a0fe6b37363ee0caf7f84b420b7c74cc2.zip |
377055 Prevent webapp classloader leaks
10 files changed, 462 insertions, 0 deletions
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AWTLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AWTLeakPreventer.java new file mode 100644 index 0000000000..4cb32719d4 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AWTLeakPreventer.java @@ -0,0 +1,43 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +import java.awt.Toolkit; + +/** + * AWTLeakPreventer + * + * See https://issues.jboss.org/browse/AS7-3733 + * + * The java.awt.Toolkit class has a static field that is the default toolkit. + * Creating the default toolkit causes the creation of an EventQueue, which has a + * classloader field initialized by the thread context class loader. + * + */ +public class AWTLeakPreventer extends AbstractLeakPreventer +{ + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + LOG.debug("Pinning classloader for java.awt.EventQueue using "+loader); + Toolkit.getDefaultToolkit(); + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AbstractLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AbstractLeakPreventer.java new file mode 100644 index 0000000000..bf3e9dfb69 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AbstractLeakPreventer.java @@ -0,0 +1,57 @@ +// ======================================================================== +// Copyright (c) 2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + + +package org.eclipse.jetty.util.preventers; + +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * AbstractLeakPreventer + * + * Abstract base class for code that seeks to avoid pinning of webapp classloaders by using the jetty classloader to + * proactively call the code that pins them (generally pinned as static data members, or as static + * data members that are daemon threads (which use the context classloader)). + * + * Instances of subclasses of this class should be set with Server.addBean(), which will + * ensure that they are called when the Server instance starts up, which will have the jetty + * classloader in scope. + * + */ +public abstract class AbstractLeakPreventer extends AbstractLifeCycle +{ + protected static final Logger LOG = Log.getLogger(AbstractLeakPreventer.class); + + /* ------------------------------------------------------------ */ + abstract public void prevent(ClassLoader loader); + + + /* ------------------------------------------------------------ */ + @Override + protected void doStart() throws Exception + { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + try + { + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + prevent(getClass().getClassLoader()); + super.doStart(); + } + finally + { + Thread.currentThread().setContextClassLoader(loader); + } + } +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AppContextLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AppContextLeakPreventer.java new file mode 100644 index 0000000000..3685ba11b8 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/AppContextLeakPreventer.java @@ -0,0 +1,36 @@ +// ======================================================================== +// Copyright (c) 2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + +package org.eclipse.jetty.util.preventers; + +import javax.imageio.ImageIO; + +/** + * AppContextLeakPreventer + * + * Cause the classloader that is pinned by AppContext.getAppContext() to be + * a container or system classloader, not a webapp classloader. + * + * Inspired by Tomcat JreMemoryLeakPrevention. + */ +public class AppContextLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + @Override + public void prevent(ClassLoader loader) + { + LOG.debug("Pinning classloader for AppContext.getContext() with "+loader); + ImageIO.getUseCache(); + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DOMLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DOMLeakPreventer.java new file mode 100644 index 0000000000..002c458c5c --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DOMLeakPreventer.java @@ -0,0 +1,52 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +import javax.xml.parsers.DocumentBuilderFactory; + +/** + * DOMLeakPreventer + * + * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498 + * + * Prevent the RuntimeException that is a static member of AbstractDOMParser + * from pinning a webapp classloader by causing it to be set here by a non-webapp classloader. + * + * Note that according to the bug report, a heap dump may not identify the GCRoot, making + * it difficult to identify the cause of the leak. + * + */ +public class DOMLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try + { + factory.newDocumentBuilder(); + } + catch (Exception e) + { + LOG.warn(e); + } + + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DriverManagerLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DriverManagerLeakPreventer.java new file mode 100644 index 0000000000..be2431f5e5 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/DriverManagerLeakPreventer.java @@ -0,0 +1,37 @@ +// ======================================================================== +// Copyright (c) 2012 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + + +package org.eclipse.jetty.util.preventers; + +import java.sql.DriverManager; + + +/** + * DriverManagerLeakPreventer + * + * Cause DriverManager.getCallerClassLoader() to be called, which will pin the classloader. + * + * Inspired by Tomcat JreMemoryLeakPrevention. + */ +public class DriverManagerLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + @Override + public void prevent(ClassLoader loader) + { + LOG.debug("Pinning DriverManager classloader with "+loader); + DriverManager.getDrivers(); + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/GCThreadLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/GCThreadLeakPreventer.java new file mode 100644 index 0000000000..471de67866 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/GCThreadLeakPreventer.java @@ -0,0 +1,60 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +import java.lang.reflect.Method; + +/** + * GCThreadLeakPreventer + * + * Prevents a call to sun.misc.GC.requestLatency pinning a webapp classloader + * by calling it with a non-webapp classloader. The problem appears to be that + * when this method is called, a daemon thread is created which takes the + * context classloader. A known caller of this method is the RMI impl. See + * http://stackoverflow.com/questions/6626680/does-java-garbage-collection-log-entry-full-gc-system-mean-some-class-called + * + * This preventer will start the thread with the longest possible interval, although + * subsequent calls can vary that. Recommend to only use this class if you're doing + * RMI. + * + * Inspired by Tomcat JreMemoryLeakPrevention. + * + */ +public class GCThreadLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + try + { + Class clazz = Class.forName("sun.misc.GC"); + Method requestLatency = clazz.getMethod("requestLatency", new Class[] {long.class}); + requestLatency.invoke(null, Long.valueOf(Long.MAX_VALUE-1)); + } + catch (ClassNotFoundException e) + { + LOG.ignore(e); + } + catch (Exception e) + { + LOG.warn(e); + } + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/Java2DLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/Java2DLeakPreventer.java new file mode 100644 index 0000000000..5d8791d5d4 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/Java2DLeakPreventer.java @@ -0,0 +1,45 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +/** + * Java2DLeakPreventer + * + * Prevent pinning of webapp classloader by pre-loading sun.java2d.Disposer class + * before webapp classloaders are created. + * + * See https://issues.apache.org/bugzilla/show_bug.cgi?id=51687 + * + */ +public class Java2DLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + try + { + Class.forName("sun.java2d.Disposer"); + } + catch (ClassNotFoundException e) + { + LOG.ignore(e); + } + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LDAPLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LDAPLeakPreventer.java new file mode 100644 index 0000000000..9bebbd1781 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LDAPLeakPreventer.java @@ -0,0 +1,47 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +/** + * LDAPLeakPreventer + * + * If com.sun.jndi.LdapPoolManager class is loaded and the system property + * com.sun.jndi.ldap.connect.pool.timeout is set to a nonzero value, a daemon + * thread is started which can pin a webapp classloader if it is the first to + * load the LdapPoolManager. + * + * Inspired by Tomcat JreMemoryLeakPrevention + * + */ +public class LDAPLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + try + { + Class.forName("com.sun.jndi.LdapPoolManager"); + } + catch (ClassNotFoundException e) + { + LOG.ignore(e); + } + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LoginConfigurationLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LoginConfigurationLeakPreventer.java new file mode 100644 index 0000000000..0f032dbebe --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/LoginConfigurationLeakPreventer.java @@ -0,0 +1,45 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +/** + * LoginConfigurationLeakPreventer + * + * The javax.security.auth.login.Configuration class keeps a static reference to the + * thread context classloader. We prevent a webapp context classloader being used for + * that by invoking the classloading here. + * + * Inspired by Tomcat JreMemoryLeakPrevention + */ +public class LoginConfigurationLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + try + { + Class.forName("javax.security.auth.login.Configuration"); + } + catch (ClassNotFoundException e) + { + LOG.warn(e); + } + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/SecurityProviderLeakPreventer.java b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/SecurityProviderLeakPreventer.java new file mode 100644 index 0000000000..dc0efcbdf7 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/preventers/SecurityProviderLeakPreventer.java @@ -0,0 +1,40 @@ +//======================================================================== +//Copyright 2012 Mort Bay Consulting Pty. Ltd. +//------------------------------------------------------------------------ +//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. +//======================================================================== + +package org.eclipse.jetty.util.preventers; + +import java.security.Security; + +/** + * SecurityProviderLeakPreventer + * + * Some security providers, such as sun.security.pkcs11.SunPKCS11 start a deamon thread, + * which will use the thread context classloader. Load them here to ensure the classloader + * is not a webapp classloader. + * + * Inspired by Tomcat JreMemoryLeakPrevention + */ +public class SecurityProviderLeakPreventer extends AbstractLeakPreventer +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.preventers.AbstractLeakPreventer#prevent(java.lang.ClassLoader) + */ + @Override + public void prevent(ClassLoader loader) + { + Security.getProviders(); + } + +} |