Check and analyze if JCR session leaks in your AEM instance

Check for and identify the cause of your AEM 6.x application JCR session leak.

Description description

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

Environment

AEM 6.4,6.5

Resolution resolution

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
  3. 12105:org.apache.jackrabbit.oak "SessionStatistics" "admin@session-12105@Aug 10, 2020 7:03:25 PM" {id=287}.
  4. The higher the id number, the later the session was created after the last AEM restart.
  5. Review the stack traces showing which code opened those sessions.
  6. 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/we-retail");
  log.info("Node: " + node.getPath());
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
}

*Note:*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/we-retail");
  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.

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f