blob: 847cc47bf6d4b69ae48aae0650cf503c11ea2fb2 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Preventing Memory Leaks</title><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><meta name="keywords" content="jetty, servlet, servlet-api, cometd, http, websocket, eclipse, maven, java, server, software"><link rel="home" href="index.html" title="Jetty : The Definitive Reference"><link rel="up" href="troubleshooting.html" title="Chapter&nbsp;35.&nbsp;Troubleshooting"><link rel="prev" href="troubleshooting-locked-files-on-windows.html" title="Troubleshooting Locked Files on Windows"><link rel="next" href="security-reports.html" title="Jetty Security Reports"><link xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" rel="shortcut icon" href="images/favicon.ico"><script type="text/javascript" src="js/shCore.js"></script><script type="text/javascript" src="js/shBrushJava.js"></script><script type="text/javascript" src="js/shBrushXml.js"></script><script type="text/javascript" src="js/shBrushBash.js"></script><script type="text/javascript" src="js/shBrushJScript.js"></script><script type="text/javascript" src="js/shBrushSql.js"></script><script type="text/javascript" src="js/shBrushProperties.js"></script><script type="text/javascript" src="js/shBrushPlain.js"></script><link type="text/css" rel="stylesheet" href="css/shCore.css"><link type="text/css" rel="stylesheet" href="css/shThemeEclipse.css"><link type="text/css" rel="stylesheet" href="css/font-awesome.min.css"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><tr><td style="width: 25%"><a href="http://www.eclipse.org/jetty"><img src="images/jetty-header-logo.png" alt="Jetty Logo"></a><br><span style="font-size: small">
Version: 9.3.0.v20150612</span></td><td style="width: 50%"><script type="text/javascript"> (function() {
var cx = '016459005284625897022:obd4lsai2ds';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script><gcse:search></gcse:search></td></tr></table><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Preventing Memory Leaks</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="troubleshooting-locked-files-on-windows.html"><i class="icon-chevron-left"></i> Previous</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;35.&nbsp;Troubleshooting<br><a accesskey="p" href="index.html"><i class="icon-home"></i> Home</a></th><td width="20%" align="right">&nbsp;<a accesskey="n" href="security-reports.html">Next <i class="icon-chevron-right"></i></a></td></tr></table><hr></div><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="jetty-callout"><h5 class="callout"><a href="http://www.webtide.com/">Contact the core Jetty developers at
<span class="website">www.webtide.com</span></a></h5><p>
private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ...
scalability guidance for your apps and Ajax/Comet projects ... development services from 1 day to full product delivery
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="preventing-memory-leaks"></a>Preventing Memory Leaks</h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="preventing-memory-leaks.html#preventing-webapp-classloader-pinning">Preventing WebApp Classloader Pinning</a></span></dt><dt><span class="section"><a href="preventing-memory-leaks.html#jsp-bugs">JSP Bugs: Permgen Problems</a></span></dt><dt><span class="section"><a href="preventing-memory-leaks.html#jvm-bugs">JVM Bugs</a></span></dt></dl></div><p>If you have memory leaks, and you have thoroughly investigated tools
like jconsole, yourkit, jprofiler, jvisualvm or any of the other profiling
and analysis tools, and you can eliminate your code as the source of the
problem, read the following sections about how to prevent memory leaks in
your application.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="preventing-webapp-classloader-pinning"></a>Preventing WebApp Classloader Pinning</h3></div></div></div><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title"><i class="icon-asterisk"></i> Note</h3><p>This feature is available for Jetty 7.6.6 and later.</p></div><p>Code that keeps references to a webapp classloader can cause memory
leaks. These leaks fall generally into two categories: static fields and
daemon threads.</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>A static field is initialized with the value of the classloader,
which happens to be a webapp classloader; as Jetty undeploys and
redeploys the webapp, the static reference lives on, meaning garbage
collecting cannot occur for the webapp classloader.</p></li><li class="listitem"><p>When Jetty starts as a daemon thread and is outside the
lifecycle of the webapp, threads have references to the context
classloader that created them, leading to a memory leak if that
classloader belongs to a webapp. For a good discussion of the issue
see <a class="link" href="http://cdivilly.wordpress.com/tag/sun-awt-appcontext/" target="_top">
Anatomy of a PermGen Memory Leak.</a></p></li></ul></div><p>We provide a number of <a class="link" href="http://download.eclipse.org/jetty/stable-9/apidocs//org/eclipse/jetty/util/preventers/package-summary.html" target="_top">
workaround classes</a> that preemptively invoke the problematic code
with the Jetty classloader, thereby ensuring the webapp classloader is not
pinned. Be aware that since some of the problematic code creates threads,
you should be selective about which preventers you enable, and use only
those that are specific to your application.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="preventers-table"></a>Preventers</h4></div></div></div><p>Jetty includes the following preventers.</p><div class="informaltable"><table border="1"><colgroup><col><col></colgroup><thead><tr><th align="left">Preventer Name</th><th align="left">Problem Addressed</th></tr></thead><tbody><tr><td>AppContextLeakPreventer</td><td>The call to <code class="code">AppContext.getAppContext()</code> keeps
a static reference to the context classloader. The JRE can
invoke AppContext in many different places.</td></tr><tr><td>AWTLeakPreventer</td><td>The <code class="code">java.awt.Toolkit</code> class has a static
field that is the default toolkit. Creating the default toolkit
causes the creation of an <code class="code">EventQueue</code>, which has a
classloader field initialized with the thread context class
loader. See <a class="link" href="https://issues.jboss.org/browse/AS7-3733" target="_top">JBoss bug
AS7-3733.</a></td></tr><tr><td>DOMLeakPreventer</td><td>DOM parsing can cause the webapp classloader to be
pinned, due to the static field <code class="code"> RuntimeException</code>
of <code class="code">
com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.</code>
<a class="link" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498" target="_top">Oracle
bug 6916498</a> specifically mentions that a heap dump might
not identify the GCRoot as the uncollected loader, making it
difficult to identify the cause of the leak.</td></tr><tr><td>DriverManagerLeakPreventer</td><td>The number of threads dedicated to accepting incoming
connections.</td></tr><tr><td>GCThreadLeakPreventer</td><td>Calls to <code class="code">sun.misc.GC.requestLatency</code> create a
daemon thread that keeps a reference to the context classloader.
A known caller of this method is the RMI impl. See <a class="link" href="http://stackoverflow.com/questions/6626680/does-java-garbage-collection-log-entry-full-gc-system-mean-some-class-called" target="_top">Stackoverflow:
Does java garbage collection log entry 'Full GC system' mean
some class called System.gc()?</a></td></tr><tr><td>Java2DLeakPreventer</td><td><code class="code">sun.java2d.Disposer</code> keeps a reference to the
classloader. See <a class="link" href="https://issues.apache.org/bugzilla/show_bug.cgi?id=51687" target="_top">ASF
bug 51687.</a></td></tr><tr><td>LDAPLeakPreventer</td><td>If <code class="code">com.sun.jndi.LdapPoolManager</code> class is
loaded and the system property <code class="code">
com.sun.jndi.ldap.connect.pool.timeout</code> is set to a
nonzero value, a daemon thread starts and keeps a reference to
the context classloader.</td></tr><tr><td>LoginConfigurationLeakPreventer</td><td>The <code class="code">javax.security.auth.login.Configuration</code>
class keeps a static reference to the thread context
classloader.</td></tr><tr><td>SecurityProviderLeakPreventer</td><td>Some security providers, such as
<code class="code">sun.security.pkcs11.SunPKCS11</code> start a deamon thread
that traps the thread context classloader.</td></tr></tbody></table></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="configuring-preventers"></a>Configuring Preventers</h4></div></div></div><p>You can individually enable each preventer by adding an instance
to a Server with the <code class="code"> addBean(Object)</code> call. Here's an
example of how to do it in code with the <code class="code">
org.eclipse.jetty.util.preventers.AppContextLeakPreventer</code>:</p><div class="informalexample"><script type="syntaxhighlighter" class="brush: java;toolbar: false">
<![CDATA[
Server server = new Server();
server.addBean(new AppContextLeakPreventer());
]]>
</script></div><p>You can add the equivalent in code to the
<code class="code">$JETTY_HOME/etc/jetty.xml</code> file or any jetty xml file that
is configuring a Server instance. Be aware that if you have more than
one Server instance in your JVM, you should configure these preventers
on just <span class="emphasis"><em>one</em></span> of them. Here's the example from code
put into xml:</p><div class="informalexample"><script type="syntaxhighlighter" class="brush: xml;toolbar: false">
<![CDATA[
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.util.preventers.AppContextLeakPreventer"/>
</Arg>
</Call>
</Configure>
]]>
</script></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="jsp-bugs"></a>JSP Bugs: Permgen Problems</h3></div></div></div><p>The JSP engine in Jetty is Jasper. This was originally developed
under the Apache Tomcat project, but over time many different project have
forked it. All Jetty versions up to 6 used Apache-based Jasper
exclusively, with Jetty 6 using Apache Jasper only for JSP 2.0. With the
advent of JSP 2.1, Jetty 6 switched to using Jasper from Sun's <a class="link" href="https://glassfish.java.net/" target="_top">Glassfish</a> project, which is
now the reference implementation.</p><p>All forks of Jasper suffer from a problem whereby using JSP tag
files puts the permgen space under pressure. This is because of the
classloading architecture of the JSP implementation. Each JSP file is
effectively compiled and its class loaded in its own classloader to allow
for hot replacement. Each JSP that contains references to a tag file
compiles the tag if necessary and then loads it using its own classloader.
If you have many JSPs that refer to the same tag file, the tag's class is
loaded over and over again into permgen space, once for each JSP. See
<a class="link" href="http://java.net/jira/browse/GLASSFISH-3963" target="_top">Glassfish bug
3963</a> and <a class="link" href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43878" target="_top">Apache
bug 43878.</a> The Apache Tomcat project has already closed this bug
with status WON'T FIX, however the Glassfish folks still have the bug open
and have scheduled it to be fixed. When the fix becomes available, the
Jetty project will pick it up and incorporate into our release
program.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="jvm-bugs"></a>JVM Bugs</h3></div></div></div><p>This section describes garbage collection and direct ByteBuffer
problems.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jvm-garbage-collection-problems"></a>Garbage Collection Problems</h4></div></div></div><p>One symptom of a cluster of JVM related memory issues is the OOM
exception accompanied by a message such as
<code class="code">java.lang.OutOfMemoryError: requested xxxx bytes for xxx. Out of
swap space?</code></p><p><a class="link" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4697804" target="_top">Oracle
bug 4697804</a> describes how this can happen in the scenario when
the garbage collector needs to allocate a bit more space during its run
and tries to resize the heap, but fails because the machine is out of
swap space. One suggested work around is to ensure that the JVM never
tries to resize the heap, by setting min heap size to max heap
size:</p><div class="informalexample"><script type="syntaxhighlighter" class="brush: plain;toolbar: false">
<![CDATA[
java -Xmx1024m -Xms1024m
]]>
</script></div><p>Another workaround is to ensure you have configured sufficient
swap space on your device to accommodate all programs you are running
concurrently.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="direct-byte-buffers"></a>Direct ByteBuffers</h4></div></div></div><p>Exhausting native memory is another issue related to JVM bugs. The
symptoms to look out for are the process size growing, but heap use
remaining relatively constant. Both the JIT compiler and nio ByteBuffers
can consume native memory. <a class="link" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6210541" target="_top">Oracle
bug 6210541</a> discusses a still-unsolved problem whereby the JVM
itself allocates a direct ByteBuffer in some circumstances while the
system never garbage collects, effectively eating native memory. Guy
Korland's blog discusses this problem <a class="link" href="http://www.jroller.com/gkorland/entry/java_s_memory_isn_t" target="_top">here</a>
and <a class="link" href="http://www.jroller.com/gkorland/entry/java_s_memory_managment_is" target="_top">here.</a>
As the JIT compiler consumes native memory, the lack of available memory
may manifest itself in the JIT as OutOfMemory exceptions such as
<code class="code">Exception in thread "CompilerThread0" java.lang.OutOfMemoryError:
requested xxx bytes for ChunkPool::allocate. Out of swap
space?</code></p><p>By default, Jetty allocates and manages its own pool of direct
ByteBuffers for io if you configure the nio SelectChannelConnector. It
also allocates MappedByteBuffers to memory-map static files via the
DefaultServlet settings. However, you could be vulnerable to this JVM
ByteBuffer allocation problem if you have disabled either of these
options. For example, if you're on Windows, you may have disabled the
use of memory-mapped buffers for the static file cache on the
DefaultServlet to avoid the file-locking problem.</p></div></div></div><script type="text/javascript">
SyntaxHighlighter.all()
</script><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="troubleshooting-locked-files-on-windows.html"><i class="icon-chevron-left"></i> Previous</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="troubleshooting.html"><i class="icon-chevron-up"></i> Top</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="security-reports.html">Next <i class="icon-chevron-right"></i></a></td></tr><tr><td width="40%" align="left" valign="top">Troubleshooting Locked Files on Windows&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html"><i class="icon-home"></i> Home</a></td><td width="40%" align="right" valign="top">&nbsp;Jetty Security Reports</td></tr></table></div><p xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><div class="jetty-callout">
See an error or something missing?
<span class="callout"><a href="http://github.com/jetty-project/jetty-documentation">Contribute to this documentation at
<span class="website"><i class="icon-github"></i> Github!</span></a></span><span style="float: right"><i>(Generated: 2015-06-15T13:18:56-05:00)</i></span></div></p><script xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1149868-7']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script></body></html>