title: Tomcat memory management
body: <p>I'm running Tomcat7, the server is quite powerful, 8 GB RAM 8-core.</p>
  
  <p><img src="https://i.stack.imgur.com/VpfDf.jpg" alt="tomcat taking a LOT of memory for nothing ?"></p>
  
  <p>My problem is that the RES memory is geting higher and higher, until the server just doesn't respond anymore, not even calling OnOutOfMemoryError.</p>
  
  <p>Tomcat configuration :</p>
  
  <pre><code>-Xms1024M
  -Xmx2048M
  -XX:PermSize=256m
  -XX:MaxPermSize=512m
  -XX:+UseConcMarkSweepGC
  -XX:OnOutOfMemoryError='/var/tomcat/conf/restart_tomcat.sh'
  </code></pre>
  
  <p>Memory informations :</p>
  
  <pre><code>Memory:     Non heap memory = 106 Mb (Perm Gen, Code Cache),
  Loaded classes = 14,055,
  Garbage collection time = 47,608 ms,
  Process cpu time = 4,296,860 ms,
  Committed virtual memory = 6,910 Mb,
  Free physical memory = 4,906 Mb,
  Total physical memory = 8,192 Mb,
  Free swap space = 26,079 Mb,
  Total swap space = 26,079 Mb
  Perm Gen memory:    88 Mb / 512 Mb    ++++++++++++
  Free disk space:    89,341 Mb 
  </code></pre>
  
  <p>The memory used by Tomcat doesn't look that high compared to the top command.</p>
  
  <p><img src="https://i.stack.imgur.com/vYI3m.jpg" alt="app memory graph"></p>
  
  <p>I also had <code>java.net.SocketException: No buffer space available</code> when trying to connect to SMTP server or when trying to connect to facebook servers.</p>
  
  <p>I use Hibernate, with c3p0 connection pool with this configuration :</p>
  
  <pre><code>        &lt;property name="hibernate.connection.driver_class"&gt;com.mysql.jdbc.Driver&lt;/property&gt;
          &lt;property name="hibernate.connection.url"&gt;jdbc:mysql://urldb/schema?autoReconnect=true&lt;/property&gt;
          &lt;property name="hibernate.connection.username"&gt;username&lt;/property&gt;
          &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.MySQL5InnoDBDialect&lt;/property&gt;
          &lt;property name="hibernate.connection.password"&gt;&lt;/property&gt;
          &lt;property name="connection.characterEncoding"&gt;UTF-8&lt;/property&gt;
  
          &lt;property name="hibernate.c3p0.acquire_increment"&gt;1&lt;/property&gt;
          &lt;property name="hibernate.c3p0.idle_test_period"&gt;300&lt;/property&gt;
          &lt;property name="hibernate.c3p0.timeout"&gt;5000&lt;/property&gt;
          &lt;property name="hibernate.c3p0.max_size"&gt;50&lt;/property&gt;
          &lt;property name="hibernate.c3p0.min_size"&gt;1&lt;/property&gt;
          &lt;property name="hibernate.c3p0.max_statement"&gt;0&lt;/property&gt;
          &lt;property name="hibernate.c3p0.preferredTestQuery"&gt;select 1;&lt;/property&gt;
          &lt;property name="hibernate.connection.provider_class"&gt;org.hibernate.connection.C3P0ConnectionProvider&lt;/property&gt;
  </code></pre>
  
  <p>I couldn't find anything... does someone have an hint of where I should be looking for ?</p>
  
  <p>Thanks!</p>
  
  <p><strong>[UPDATE 1]HEAP DUMP :</strong> </p>
  
  <pre><code>HEAP HISTOGRAM :
  
  class [C                                    269780  34210054
  class [B                                    5600    33836661
  class java.util.HashMap$Entry               221872  6212416
  class [Ljava.util.HashMap$Entry;            23797   6032056
  class java.lang.String                      271170  5423400
  class org.hibernate.hql.ast.tree.Node       103588  4972224
  class net.bull.javamelody.CounterRequest    28809   2996136
  class org.hibernate.hql.ast.tree.IdentNode  23461   2205334
  class java.lang.Class                       14677   2113488
  class org.hibernate.hql.ast.tree.DotNode    13045   1852390
  class [Ljava.lang.String;                   48506   1335600
  class [Ljava.lang.Object;                   12997   1317016 
  
  
  Instance Counts for All Classes (excluding platform) :
  
  103588 instances of class org.hibernate.hql.ast.tree.Node
  33366 instances of class antlr.ANTLRHashString
  28809 instances of class net.bull.javamelody.CounterRequest
  24436 instances of class org.apache.tomcat.util.buf.ByteChunk
  23461 instances of class org.hibernate.hql.ast.tree.IdentNode
  22781 instances of class org.apache.tomcat.util.buf.CharChunk
  22331 instances of class org.apache.tomcat.util.buf.MessageBytes
  13045 instances of class org.hibernate.hql.ast.tree.DotNode
  10024 instances of class net.bull.javamelody.JRobin
  9084 instances of class org.apache.catalina.loader.ResourceEntry
  7931 instances of class org.hibernate.hql.ast.tree.SqlNode 
  </code></pre>
  
  <p><strong>[UPDATE 2] server.xml :</strong></p>
  
  <pre><code>&lt;Connector port="8080" protocol="HTTP/1.1"
                 connectionTimeout="20000"
                 redirectPort="8443"
                 URIEncoding="UTF-8"
                 maxThreads="150"
                 minSpareThreads="25"
                 maxSpareThreads="75"
                 enableLookups="false"
                 acceptCount="1024"
                 server="unknown"
                 address="public_ip"
      /&gt;
  </code></pre>
  
  <p>****[UPDATE 3] Output from log files :  **** </p>
  
  <pre><code>    2012-06-04 06:18:24,152 [http-bio-ip-8080-exec-3500] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/api].[Jersey REST Service]- Servlet.ser
  vice() for servlet [Jersey REST Service] in context with path [/socialapi] threw exception
  java.net.SocketTimeoutException: Read timed out
  
      at java.net.SocketInputStream.socketRead0(Native Method)
      at java.net.SocketInputStream.read(SocketInputStream.java:129)
      at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:532)
      at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501)
      at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563)
      at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118)
      at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326)
      at org.apache.coyote.Request.doRead(Request.java:422)
  </code></pre>
  
  <p><strong>[UPDATE 4] ServletContext</strong></p>
  
  <p>I use a <code>ServletContextListener</code>in my application to instanciate controllers and keep a reference with <code>event.getServletContext().setAttribute</code>. Those controllers loads configurations and translations (the 88Mb in Perm).</p>
  
  <p>Then to use the database i use : </p>
  
  <pre><code>SessionFactory sf = dbManager.getSessionFactory(DatabaseManager.DB_KEY_DEFAULT);
  Session session = sf.openSession();
  Transaction tx = null; 
  
  try {
      tx = session.beginTransaction();
  
      //Do stuuf
  
      tx.commit();
  
  } catch (Exception e){
      //Do something
  } finally {
      session.close();
  }
  </code></pre>
  
  <ol>
  <li>Could this be the source of a leak ?</li>
  <li>Why not to use Manual transaction/session, and how would you do then ?</li>
  </ol>