title: Memory leak on Liferay 6.2 migration
body: <p>I've migrated a Liferay 6.2-CE-GA2 server from Liferay 6.1.1-ce-ga2.</p>
  
  <p>I made a few changes in custom hooks and themes to addapt to the new version.</p>
  
  <p>On locale I have never had a problem with memory nor with the 6.1 version, but once in production, server runs out of memory in a few hours.</p>
  
  <p>I tried to adjust heap parameters and increasing server memory (from 2GB to 3GB) but it seems that the heap keeps growking slowly but non-stopping, until I get an <code>OutOfMemory: Java heap space</code> or, if I grant bigger limits to the heap, system runs out of memory.</p>
  
  <p>I've been some days studying catalina.out, trying to minimize warnings and errors and this is the only interesting things I've seen  during a shutdown-reboot process (I replaced all domain names on logs):</p>
  
  <pre><code>[on shutdown]
  WARN: The method class org.apache.commons.logging.impl.SLF4JLogFactory#release() was invoked.
  WARN: Please see http://www.slf4j.org/codes.html#release for an explanation.
  
  [...]
  
  28-xul-2014 16:53:51 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
  SEVERE: The web application [] appears to have started a thread named [org.python.google.common.base.internal.Finalizer] but has failed to stop it. This is very likely to create a memory leak.
  28-xul-2014 16:53:51 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
  SEVERE: The web application [] appears to have started a thread named [Thread-26] but has failed to stop it. This is very likely to create a memory leak.
  28-xul-2014 16:53:51 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
  SEVERE: The web application [] appears to have started a thread named [Thread-27] but has failed to stop it. This is very likely to create a memory leak.
  
  [...]
  
  16:55:40,517 ERROR [liferay/hot_deploy-1][JDBCExceptionReporter:82] Batch entry 0 insert into CalendarBooking (uuid_, groupId, companyId, userId, userName, createDate, modifiedDate, resourceBlockId, calendarId, calendarResourceId, parentCalendarBookingId, title, description, location, startTime, endTime, allDay, recurrence, firstReminder, firstReminderType, secondReminder, secondReminderType, status, statusByUserId, statusByUserName, statusDate, calendarBookingId) values ('985aac08-6457-484c-becb-2c4964805158', '10545', '10154', '10196', 'Carlos Ces', '2012-06-06 06:26:41.431000 +01:00:00', '2012-06-06 06:26:41.431000 +01:00:00', '0', '550617', '550571', '565201', 'Master Class de improvisación e tango contemporáneo con Jorge Retamoza', '&lt;p&gt;_    &lt;a href="http://www.rrrrrr.es/cultura/-/blogs/master-class-de-improvisacion-e-tango-contemporaneo-con-jorge-retamoza"&gt;Master Class con Jorge Retamoza. &lt;/a&gt;&lt;/p&gt;_&lt;p&gt;_    &lt;a href="http://www.rrrrrr.es/cultura/-/blogs/master-class-de-improvisacion-e-tango-contemporaneo-con-jorge-retamoza"&gt;Organiza: Escola de Música de rrrrrr. Colabora: Concello de rrrrrr.&lt;/a&gt;&lt;/p&gt;', 'Auditorio de rrrrrr', '1339246800000', '1339257600000', '0', '', '900000', 'email', '300000', 'email', '0', '10196', 'Carlos Ces', '2012-06-06 06:26:41.431000 +01:00:00', '565201') was aborted.  Call getNextException to see the cause. [Sanitized]
  16:55:40,518 ERROR [liferay/hot_deploy-1][JDBCExceptionReporter:82] ERROR: duplicate key value violates unique constraint "ix_f4c61797"
  16:55:40,536 ERROR [liferay/hot_deploy-1][SerialDestination:68] Unable to process message {destinationName=liferay/hot_deploy, response=null, responseDestinationName=null, responseId=null, payload=null, values={command=deploy, companyId=0, servletContextName=calendar-portlet}}
  com.liferay.portal.kernel.messaging.MessageListenerException: com.liferay.portal.kernel.dao.orm.ORMException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
      at com.liferay.portal.kernel.messaging.BaseMessageListener.receive(BaseMessageListener.java:32)
      at com.liferay.portal.kernel.messaging.InvokerMessageListener.receive(InvokerMessageListener.java:72)
      at com.liferay.portal.kernel.messaging.SerialDestination$1.run(SerialDestination.java:65)
      at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask._runTask(ThreadPoolExecutor.java:682)
      at com.liferay.portal.kernel.concurrent.ThreadPoolExecutor$WorkerTask.run(ThreadPoolExecutor.java:593)
      at java.lang.Thread.run(Thread.java:636)
  Caused by: com.liferay.portal.kernel.dao.orm.ORMException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
      [...]
      ... 5 more
  Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
      at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
      at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
      [...]
      ... 62 more
  Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into CalendarBooking (uuid_, groupId, companyId, userId, userName, createDate, modifiedDate, resourceBlockId, calendarId, calendarResourceId, parentCalendarBookingId, title, description, location, startTime, endTime, allDay, recurrence, firstReminder, firstReminderType, secondReminder, secondReminderType, status, statusByUserId, statusByUserName, statusDate, calendarBookingId) values ('985aac08-6457-484c-becb-2c4964805158', '10545', '10154', '10196', 'Carlos Ces', '2012-06-06 06:26:41.431000 +01:00:00', '2012-06-06 06:26:41.431000 +01:00:00', '0', '550617', '550571', '565201', 'Master Class de improvisación e tango contemporáneo con Jorge Retamoza', '&lt;p&gt;_  &lt;a href="http://www.rrrrrr.es/cultura/-/blogs/master-class-de-improvisacion-e-tango-contemporaneo-con-jorge-retamoza"&gt;Master Class con Jorge Retamoza. &lt;/a&gt;&lt;/p&gt;_&lt;p&gt;_    &lt;a href="http://www.rrrrrr.es/cultura/-/blogs/master-class-de-improvisacion-e-tango-contemporaneo-con-jorge-retamoza"&gt;Organiza: Escola de Música de rrrrrr. Colabora: Concello de rrrrrr.&lt;/a&gt;&lt;/p&gt;', 'Auditorio de rrrrrr', '1339246800000', '1339257600000', '0', '', '900000', 'email', '300000', 'email', '0', '10196', 'Carlos Ces', '2012-06-06 06:26:41.431000 +01:00:00', '565201') was aborted.  Call getNextException to see the cause. [Sanitized]
      at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2621)
      at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1837)
      [...]
      ... 68 more
  </code></pre>
  
  <p>Then server runs properly for 5 hours with some spared warnings each few minutes:</p>
  
  <pre><code>23:39:09,275 WARN  [ajp-apr-8009-exec-20][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.com/rrrrrr25n/notadeprensa on 56_INSTANCE_rk7ADlb9Ui2w
  23:43:51,234 WARN  [ajp-apr-8009-exec-19][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.org/feiron/normas on 56_INSTANCE_jh6ewEPuvvjb
  23:46:59,568 WARN  [ajp-apr-8009-exec-5][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.es/recursos-servizossociais on 56_INSTANCE_4eX2GzETiAQb
  23:55:51,177 WARN  [ajp-apr-8009-exec-5][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.es/cans on 56_INSTANCE_4eX2GzETiAQb
  00:00:13,713 WARN  [ajp-apr-8009-exec-24][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.es/rexistro on 56_INSTANCE_4eX2GzETiAQb
  00:00:25,822 WARN  [ajp-apr-8009-exec-24][SecurityPortletContainerWrapper:623] Reject process action for http://www.rrrrrr.es/plenos on 110_INSTANCE_acNEFnslrX8c
  </code></pre>
  
  <p>And then memory problems begin. I post the first errors on log:</p>
  
  <pre><code>Exception in thread "http-apr-8080-exec-4" java.lang.OutOfMemoryError: Java heap space
  01:00:01,223 ERROR [MemoryQuartzSchedulerEngineInstance_Worker-3][SimpleThreadPool:120] Error while executing the Runnable: 
  java.lang.OutOfMemoryError: Java heap space
  Exception in thread "fileinstall-/home/rrrrrr/liferay-portal-6.2-ce-ga2/data/osgi/modules" Exception in thread "ajp-apr-8009-AsyncTimeout" Exception in thread "ajp-apr-8009-exec-21"   at java.util.LinkedHashMap.createEntry(LinkedHashMap.java:441)
      at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:423)
      at java.util.HashMap.put(HashMap.java:402)
  Exception in thread "ajp-apr-8009-exec-24"  at sun.util.resources.OpenListResourceBundle.loadLookup(OpenListResourceBundle.java:134)
  Exception in thread "MemoryQuartzSchedulerEngineInstance_QuartzSchedulerThread" Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]"    at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(OpenListResourceBundle.java:113)
  Exception in thread "ajp-apr-8009-exec-35" Exception in thread "ajp-apr-8009-exec-36" Exception in thread "ajp-apr-8009-exec-29" Exception in thread "ajp-apr-8009-exec-37"     at sun.util.resources.OpenListResourceBundle.handleGetKeys(OpenListResourceBundle.java:91)
      at sun.util.LocaleServiceProviderPool.getLocalizedObjectImpl(LocaleServiceProviderPool.java:353)
  Exception in thread "ajp-apr-8009-exec-33" Exception in thread "ajp-apr-8009-exec-34" Exception in thread "ajp-apr-8009-exec-30"    at sun.util.LocaleServiceProviderPool.getLocalizedObject(LocaleServiceProviderPool.java:284)
  Exception in thread "ajp-apr-8009-exec-28" Exception in thread "ajp-apr-8009-exec-31" Exception in thread "http-apr-8080-AsyncTimeout" Exception in thread "http-apr-8080-exec-5" Exception in thread "http-apr-8080-exec-2" Exception in thread "liferay/scheduler_dispatch-3" Exception in thread "ajp-apr-8009-exec-41"  at sun.util.TimeZoneNameUtility.retrieveDisplayNames(TimeZoneNameUtility.java:111)
      at sun.util.TimeZoneNameUtility.retrieveDisplayNames(TimeZoneNameUtility.java:99)
      at java.util.TimeZone.getDisplayNames(TimeZone.java:418)
      at java.util.TimeZone.getDisplayName(TimeZone.java:369)
      at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1110)
      at java.text.SimpleDateFormat.format(SimpleDateFormat.java:899)
      at java.text.SimpleDateFormat.format(SimpleDateFormat.java:869)
      at org.apache.tomcat.util.http.ServerCookie.appendCookieValue(ServerCookie.java:254)
      at org.apache.catalina.connector.Response.generateCookieString(Response.java:1032)
      at org.apache.catalina.connector.Response.addCookie(Response.java:974)
      at org.apache.catalina.connector.ResponseFacade.addCookie(ResponseFacade.java:381)
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at com.liferay.portal.kernel.servlet.HttpOnlyCookieServletResponse.addCookie(HttpOnlyCookieServletResponse.java:62)
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse.addCookie(MetaInfoCacheServletResponse.java:128)
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse.addCookie(MetaInfoCacheServletResponse.java:128)
  01:02:56,362 ERROR [PersistedQuartzSchedulerEngineInstance_QuartzSchedulerThread][ErrorLogger:120] An error occurred while scanning for the next triggers to fire.
  org.quartz.JobPersistenceException: Failed to obtain DB connection from data source 'ds': java.lang.OutOfMemoryError: Java heap space [See nested exception: java.lang.OutOfMemoryError: Java heap space]
      at org.quartz.impl.jdbcjobstore.JobStoreSupport.getConnection(JobStoreSupport.java:771)
      at org.quartz.impl.jdbcjobstore.JobStoreTX.getNonManagedTXConnection(JobStoreTX.java:71)
      at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3808)
      at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2751)
      at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:264)
  Caused by: java.lang.OutOfMemoryError: Java heap space
      at javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:58)
      at com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse.addCookie(MetaInfoCacheServletResponse.java:128)
      at com.liferay.portal.kernel.util.CookieKeys.addCookie(CookieKeys.java:99)
      at com.liferay.portal.kernel.util.CookieKeys.addCookie(CookieKeys.java:63)
      at com.liferay.portal.language.LanguageImpl.updateCookie(LanguageImpl.java:751)
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  01:03:00,917 ERROR [QuartzScheduler_PersistedQuartzSchedulerEngineInstance-NON_CLUSTERED_MisfireHandler][PortalJobStore:120] MisfireHandler: Error handling misfires: Unexpected runtime exception: Index: 0, Size: 0
  org.quartz.JobPersistenceException: Unexpected runtime exception: Index: 0, Size: 0 [See nested exception: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0]
      at org.quartz.impl.jdbcjobstore.JobStoreSupport.doRecoverMisfires(JobStoreSupport.java:3200)
      at org.quartz.impl.jdbcjobstore.JobStoreSupport$MisfireHandler.manage(JobStoreSupport.java:3947)
      at org.quartz.impl.jdbcjobstore.JobStoreSupport$MisfireHandler.run(JobStoreSupport.java:3968)
  Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
      at java.util.ArrayList.rangeCheck(ArrayList.java:571)
      at java.util.ArrayList.get(ArrayList.java:349)
      at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1689)
      at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
      at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
      at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
      at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
      at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.countMisfiredTriggersInState(StdJDBCDelegate.java:416)
      at org.quartz.impl.jdbcjobstore.JobStoreSupport.doRecoverMisfires(JobStoreSupport.java:3176)
      ... 2 more
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  Exception in thread "fileinstall-/home/rrrrrr/liferay-portal-6.2-ce-ga2/data/osgi/portal" java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  java.lang.OutOfMemoryError: Java heap space
  </code></pre>
  
  <p>I have some custom themes and hooks that I now post. I wonder there has to be a memory leak anywhere on them, but i cannot find it.</p>
  
  <p>First, I have a custom <code>Application Display Template</code>for Blogs:</p>
  
  <pre><code>&lt;div class="cr-blog container-fluid"&gt;
   #foreach ($entry in $entries)
   &lt;div class="entry-content"&gt;
    #set ($viewUrl = $currentURL.replaceFirst("\?.*$","") + "/-/blogs/" + $entry.getUrlTitle())
    #set($img_ini=$entry.content.indexOf("&lt;img"))
  
    #if ($img_ini &gt;= 0)
     #set($img_end=$entry.content.indexOf("&gt;",$img_ini) + 1)
     #set($first_img_tag= $entry.content.substring($img_ini, $img_end))
  
     #set($first_img_url=$first_img_tag.replaceFirst("&lt;img.*src=\"",""))
     #set($first_img_url=$first_img_url.replaceFirst("\".*","")) 
    #end
  
    &lt;div class="entry-extract"&gt;
  
     #if ($img_ini &gt;= 0)
     &lt;div class="extract-thumbnail"&gt;
       &lt;a href="$viewUrl"&gt;
        &lt;img src="$escapeTool.html($first_img_url)" /&gt;
       &lt;/a&gt;
     &lt;/div&gt;
     #end
  
     &lt;div class="extract-title"&gt;
      &lt;a href="$viewUrl"&gt;&lt;span&gt;$entry.title&lt;/span&gt;&lt;/a&gt;
     &lt;/div&gt;
  
  
     &lt;div class="extract-content"&gt;
      &lt;a href="$viewUrl"&gt;
       &lt;span class="extract-date"&gt;$dateFormats.getSimpleDateFormat("dd MMMMM yyyy HH:mm", $locale).format($entry.displayDate)&lt;/span&gt;
        #set($plain_content = $entry.content.replaceAll("&lt;/?[^&gt;]+/?&gt;", ""))
        #set($res_length = 240)
        #if ($res_length &gt; $plain_content.length())
         #set($res_length = $plain_content.length())
        #end
        &lt;p&gt;
         $plain_content.substring(0,$res_length) ...
        &lt;/p&gt;
      &lt;/a&gt;
     &lt;/div&gt;
    &lt;/div&gt;
   &lt;/div&gt;
   #end
  &lt;/div&gt;
  </code></pre>
  
  <p>Custom hook Blogshome overrides some jsps from blogs_aggregator.</p>
  
  <p>view_entries.jspf</p>
  
  <pre><code>&lt;c:choose&gt;
      &lt;c:when test="&lt;%= results.isEmpty() %&gt;"&gt;
          &lt;liferay-ui:message key="there-are-no-blogs" /&gt;
  
          &lt;br /&gt;&lt;br /&gt;
      &lt;/c:when&gt;
      &lt;c:otherwise&gt;
  
          &lt;%
  
          if (displayStyle.startsWith("extract-side-events")) {
  
              List&lt;BlogsEntry&gt; eventsColumn = new ArrayList&lt;BlogsEntry&gt;();
              List&lt;BlogsEntry&gt; mainColumn = new ArrayList&lt;BlogsEntry&gt;();
  
              for (int i=0; i&lt; results.size(); i++) {
                  BlogsEntry entry = (BlogsEntry) results.get(i);
  
                  if (entry.getDisplayDate().after(new Date())) {
                      searchContainer.setTotal(searchContainer.getTotal() - 1);
                      continue;
                  }
  
  
  
                  boolean isEvent = ((Boolean) entry.getExpandoBridge().getAttribute("evento"));
  
                  if (isEvent) eventsColumn.add(entry);
                  mainColumn.add(entry); /* change: add ALL to mainColumn; events are duplicated on side */
              }
  
                          /* reorder eventsColumn */
  
                          TreeMap&lt;Date, BlogsEntry&gt; next= new TreeMap&lt;Date, BlogsEntry&gt;();
              List&lt;BlogsEntry&gt; toRemove = new ArrayList&lt;BlogsEntry&gt;();
  
                  for (BlogsEntry entry: eventsColumn) {
                                  Date ini = (Date) entry.getExpandoBridge().getAttribute("evento-inicio");
                                  Date end = (Date) entry.getExpandoBridge().getAttribute("evento-remate");
                                  Date now = new Date();
  
                                  if (ini.before(now) &amp;&amp; (end.after(now))) {
                      next.put(end, entry);
                      /* mainColumn.remove(entry); */
                  } else if (end.before(now)) {
                      toRemove.add(entry);
                  } else {
                      next.put(ini, entry);
                      /* mainColumn.remove(entry); */
                  }
                          }
              eventsColumn.removeAll(toRemove);
  
              /* third rearrangement: current &amp; next are visible; past are pushed to mainColumn */
              /* current ordered by end; next ordered by ini */
  
                          ArrayList&lt;BlogsEntry&gt; lNext = new ArrayList&lt;BlogsEntry&gt;(next.values());
  
                          %&gt; &lt;div class="home-events"&gt;
                  &lt;div class="events-showdown" id="events-showdown"&gt;
  
  
              &lt;%
                  if (!lNext.isEmpty()) { 
  
                                  for (BlogsEntry entry: lNext) {
                                          %&gt;  
                              &lt;div class="carousel-item"&gt;
                                                  &lt;%@ include file="/html/portlet/blogs_aggregator/view_entry_extract.jspf" %&gt;
                              &lt;/div&gt;
                                          &lt;%                                    
                                  }
                  }
              %&gt;
  
                  &lt;/div&gt;
                  &lt;script&gt;
                      YUI().use('aui-carousel', function(Y) { new Y.Carousel( {contentBox: '#events-showdown',
                          height: 320, width: 600, intervalTime: 5 }).render(); });
                  &lt;/script&gt;
  &lt;%--
                  &lt;div class="home-events-nav"&gt;
                      &lt;button type="button" class="btn btn-default btn-large"
                      onclick="document.getElementById('events-showdown').style.right =50"&gt;
                          &lt;span class="glyphicon glyphicon-chevron-right"&gt;&lt;/span&gt;
                      &lt;/button&gt;
                  &lt;/div&gt;
  --%&gt;
              &lt;/div&gt; &lt;%
  
  
                          %&gt; &lt;div class="home-blogs container-fluid" &gt; &lt;%                    
                          for (BlogsEntry entry: mainColumn) {
                                      %&gt;  
                                          &lt;%@ include file="/html/portlet/blogs_aggregator/view_entry_extract.jspf" %&gt;
                                      &lt;%
                          }
                          %&gt; &lt;/div&gt; &lt;%
  
  
                  /* original blogs styles */        
                  } else {
  
              for (int i = 0; i &lt; results.size(); i++) {
                  BlogsEntry entry = (BlogsEntry)results.get(i);
  
                  if (entry.getDisplayDate().after(new Date())) {
                      searchContainer.setTotal(searchContainer.getTotal() - 1);
                      continue;
                  }
              %&gt;  
                  &lt;%@ include file="/html/portlet/blogs_aggregator/view_entry_content.jspf" %&gt;
              &lt;%
              }
          }
          %&gt;
  
      &lt;/c:otherwise&gt;
  &lt;/c:choose&gt;
  
  &lt;c:if test="&lt;%= enableRssSubscription %&gt;"&gt;
  
      &lt;%
      StringBundler rssURLParams = new StringBundler();
  
      if (selectionMethod.equals("users")) {
          if (organizationId &gt; 0) {
              rssURLParams.append("&amp;organizationId=");
              rssURLParams.append(organizationId);
          }
          else {
              rssURLParams.append("&amp;companyId=");
              rssURLParams.append(company.getCompanyId());
          }
      }
      else {
          rssURLParams.append("&amp;groupId=");
          rssURLParams.append(themeDisplay.getScopeGroupId());
      }
      %&gt;
  
      &lt;span class="button"&gt;
          &lt;liferay-ui:icon
              image="rss"
              label="&lt;%= true %&gt;"
              method="get"
              target="_blank"
              url='&lt;%= themeDisplay.getPathMain() + "/blogs_aggregator/rss?p_l_id=" + plid + rssURLParams %&gt;'
          /&gt;
      &lt;/span&gt;
  &lt;/c:if&gt;
  
  &lt;c:if test="&lt;%= !results.isEmpty() %&gt;"&gt;
      &lt;div class="search-container"&gt;
          &lt;liferay-ui:search-paginator searchContainer="&lt;%= searchContainer %&gt;" /&gt;
      &lt;/div&gt;
  &lt;/c:if&gt;
  </code></pre>
  
  <p>view_entry_extract.jspf</p>
  
  <pre><code>&lt;c:if test="&lt;%= BlogsEntryPermission.contains(permissionChecker, entry, ActionKeys.VIEW) %&gt;"&gt;
      &lt;div class="entry-content"&gt;
  
          &lt;%
          PortletURL showBlogEntryURL = renderResponse.createRenderURL();
  
          showBlogEntryURL.setParameter("struts_action", "/blogs_aggregator/view_entry");
          showBlogEntryURL.setParameter("entryId", String.valueOf(entry.getEntryId()));
  
          StringBundler sb = new StringBundler(8);
  
          StringBundler ab = new StringBundler(8);
          ab.append(themeDisplay.getURLPortal());
          ab.append(GroupLocalServiceUtil.getGroup(entry.getGroupId()).getFriendlyURL());
          ab.append("/-/blogs/");
          ab.append(entry.getUrlTitle());
  
          String viewEntryURL = ab.toString();
  
          sb.append("&amp;showAllEntries=1");
  
          String viewAllEntriesURL = sb.toString();
  
          User user2 = UserLocalServiceUtil.getUserById(entry.getUserId());
          %&gt;
  
          &lt;div class="entry-header"&gt;
  
              &lt;c:if test='&lt;%= (Boolean) entry.getExpandoBridge().getAttribute("evento")%&gt;'&gt;
                  &lt;div class="event-schedule"&gt;
  
          &lt;%
  
                          Calendar iniDate = com.liferay.portal.kernel.util.CalendarFactoryUtil.getCalendar(timeZone);
                          Calendar endDate = com.liferay.portal.kernel.util.CalendarFactoryUtil.getCalendar(timeZone);
                          iniDate.setTime(((Date) entry.getExpandoBridge().getAttribute("evento-inicio")));
                          endDate.setTime(((Date) entry.getExpandoBridge().getAttribute("evento-remate")));
                                                                              boolean sameDay = false;
  
                          if ((iniDate.get(Calendar.DAY_OF_YEAR) == endDate.get(Calendar.DAY_OF_YEAR))
                           &amp;&amp; (iniDate.get(Calendar.YEAR) == endDate.get(Calendar.YEAR))) 
                  sameDay = true;
  
              String diaDaSemana = (new SimpleDateFormat("EEEE", locale)).format(iniDate.getTime());
              String numeroDeDia = (new SimpleDateFormat("d", locale)).format(iniDate.getTime());
              String mes = (new SimpleDateFormat("MMMM", locale)).format(iniDate.getTime());
  //          String hora = (new SimpleDateFormat("HH:mm", locale)).format(iniDate.getTime()) + "h"; 
              String hora = (iniDate.get(Calendar.HOUR_OF_DAY) +  new SimpleDateFormat(":mm", locale).format(iniDate.getTime()) + "h");
  
              String numeroDeDiaFin = StringPool.BLANK;
              String mesFin = StringPool.BLANK;
              if (!sameDay) {
                  numeroDeDiaFin = (new SimpleDateFormat("d", locale)).format(endDate.getTime());
                  mesFin = (new SimpleDateFormat("MMMM", locale)).format(endDate.getTime());
              }
  
          %&gt;
  
          &lt;%
              if (sameDay) {
          %&gt;
              &lt;div class='event-date'&gt;
                  &lt;%= numeroDeDia %&gt;
              &lt;/div&gt;
              &lt;div class='event-data'&gt;
                  &lt;div class="event-month"&gt;&lt;%= mes  %&gt;&lt;/div&gt;
                  &lt;div class="event-day"&gt;&lt;%= diaDaSemana  %&gt;&lt;/div&gt;
                  &lt;div class="event-time"&gt;&lt;%= hora  %&gt;&lt;/div&gt;
              &lt;/div&gt;
  
          &lt;%
              } else {
          %&gt;
              &lt;div class='event-date'&gt;
                  &lt;%= numeroDeDia %&gt;
              &lt;/div&gt;
              &lt;div class='event-data'&gt;
                  &lt;div class="event-month"&gt;&lt;%= mes  %&gt;&lt;/div&gt;
                  &lt;div class="event-day"&gt;&lt;%= diaDaSemana  %&gt;&lt;/div&gt;
                  &lt;div class="event-time"&gt;&lt;liferay-ui:message key="rrrrrr.events.until" /&gt; &lt;%= numeroDeDiaFin %&gt; 
                              &lt;liferay-ui:message key="rrrrrr.events.of" /&gt; &lt;%= mesFin  %&gt;&lt;/div&gt;
              &lt;/div&gt;
  
          &lt;%
  
              }
          %&gt;          
  
                  &lt;/div&gt;
              &lt;/c:if&gt;
  
  
          &lt;/div&gt;
  
          &lt;div class="entry-extract"&gt;
  
              &lt;%
  
              String resumeText = StringPool.BLANK;
              String resumeImage = StringPool.BLANK;
              int extLength = 240;
  
              if (entry.isSmallImage()) {
                  if (Validator.isNotNull(entry.getSmallImageURL()))
                      resumeImage = entry.getSmallImageURL();
                  else
                      resumeImage = themeDisplay.getPathImage() + "/journal/article?img_id=" + entry.getSmallImageId() + "&amp;t=" + WebServerServletTokenUtil.getToken(entry.getSmallImageId()) ;
                  resumeImage.trim();
              }
  
              /* if no small image, extract first */
              if ((resumeImage == null) || (resumeImage.isEmpty())) {
  
                  java.util.regex.Pattern p = java.util.regex.Pattern.compile("src=['\"]([^'\"]+)['\"]");
                  java.util.regex.Matcher m = p.matcher(entry.getContent());
                  if (m.find())
                      resumeImage = m.group().substring(5, m.group().length() -1);
              }
  
              resumeText = HtmlUtil.stripHtml(entry.getDescription());
              resumeText.trim();
  
              /* if no resume description, extract text */
              if ((resumeText == null) || (resumeText.isEmpty())) {
                  resumeText = HtmlUtil.escape(StringUtil.shorten(HtmlUtil.extractText(entry.getContent()), extLength));
              }
  
              %&gt;
  
              &lt;div class="extract-thumbnail"&gt;
                  &lt;a href="&lt;%= viewEntryURL %&gt;"  style="background-image: url('&lt;%= HtmlUtil.escape(resumeImage) %&gt;')"&gt;
                      &lt;img class="asset-small-image" src="&lt;%= HtmlUtil.escape(resumeImage) %&gt;"/&gt; 
                  &lt;/a&gt;
              &lt;/div&gt;
  
              &lt;div class="extract-title"&gt;
                  &lt;a href="&lt;%= viewEntryURL %&gt;"&gt;&lt;%= HtmlUtil.escape(entry.getTitle()) %&gt;&lt;/a&gt;
              &lt;/div&gt;
  
              &lt;div class="extract-content"&gt;
                  &lt;a href="&lt;%= viewEntryURL %&gt;"&gt;
                      &lt;span class="extract-scope"&gt;&lt;%= GroupLocalServiceUtil.getGroup(entry.getGroupId()).getDescriptiveName() %&gt;&lt;/span&gt; 
                      &lt;span class="extract-date"&gt;&lt;%= dateFormatDateTime.format(entry.getDisplayDate()) %&gt;&lt;/span&gt; 
                      &lt;span&gt;&lt;%= " " + resumeText %&gt;&lt;/span&gt;
                  &lt;/a&gt;
              &lt;/div&gt;
  
          &lt;/div&gt;
  
      &lt;/div&gt;
  </code></pre>
  
  <p>I am unable to guess any memory leak there, but there has to be! I've spent few weeks trying to find a bug (deactivating hooks to see if errors persisted) but couldn't come to a clue.</p>
  
  <p>Does anybody see something potentially dangerous in my code? Wich other way can I trace Java memory usage to fetch for leaks?</p>