Check if your AEM6.x application has a JCR session leak and track down the source.

Environment

AEM 6.x

Steps

I. Check if there is a session leak

  1. Go to http://host:port/system/console/jmx and log in as admin.
  2. Use the browser's search feature to find all occurrences of SessionStatistics objects on the page.
  3. If you find over 500, then there is a session leak.

II. Identify the code that is leaking sessions

If you found a session leak, then follow the steps below to find what is causing it.

  1. Scroll down the page to the SessionStatistics objects.
  2. Open some of the SessionStatistics objects in a new browser tab by [Ctrl]+Clicking some that have a later timestamp or higher id number listed.  For example the one below has an id of 12105:org.apache.jackrabbit.oak "SessionStatistics" "admin@session-12105@Aug 10, 2016 7:03:25 PM" {id=287}. The higher the id number, the later the session was created after the last AEM restart.
  3. Review the stack traces showing which code opened those sessions.
  4. Search for application java packages in the stack.  If the code is part of your application, then see the next section below.

III. Fix the session leak

To prevent and fix JCR session leaks:

  • If you open a javax.jcr.Session in your code then always close it via Session.logout()
  • If you open a org.apache.sling.api.resource.ResourceResolver in your code then always close it via ResourceResolver.close()

Closing Session objects:

The code below leaves a session left open:

try {
Session session = repository.loginAdministrative(null);
Node node = session.getNode("/content/geometrixx");
  log.info("Node: " + node.getPath());
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
}

Бележка:

In addition to not only closing the session, this code also calls repository.loginAdministrative to open it. This way of opening sessions has been deprecated in later releases of AEM for security reasons.

To close the session you would wrap the code with a try/finally block and call session.logout():

Session session = null;
try {
session = repository.loginAdministrative(null);
// use session
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
} finally {
if (session != null && session.isLive()) {
session.logout();
}
}

Be careful when you create a session or share one.  When you share a session across objects, then it makes it harder to track where it was opened and when it has to be closed.  Also, sessions should never be shared across Java Threads.

Closing ResourceResolver objects:

The code below leaves a ResourceResolver open:

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  Resource resource = resourceResolver.getResource("/content/geometrixx");
  log.info("Resource: " + res.getPath());
} catch(Exception e){
log.error(e.getMessage());
}

To close out the resourceResolver, wrap the code with a try/finally block and call resourceResolver.close():

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  // use ResourceResolver
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if(resourceResolver != null && resourceResolver.isLive()) {
resourceResolver.close();
  }
}

Important Note

Session and ResourceResolver objects that are obtained via the SlingRequest or WorkflowSession should not to be closed by your application.  For example:

slingRequest.getResourceResolver().adaptTo(Session.class);
//Or
workflowSession.getSession();

That resolver and session will be closed automatically after the request has been processed.

Този материал е лицензиран под лиценз Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported  Публикациите в Twitter™ и Facebook не попадат под клаузите на Creative Commons.

Правни бележки   |   Правила за онлайн поверителност