Skip to content
Advertisement

Measure memory consumption with all HttpSessions in Tomcat at an arbitrary point in time

I want to measure the percentage of memory used by HttpSession in a web application.

Is there any way to measure memory consumption with all HttpSessions in a running Tomcat instance at an arbitrary point in time without modifying the application?

What I have tried

  • In Tomcat, the concrete class of HttpSession is org.apache.catalina.session.StandardSession. I have profiled the application with VisualVM and specified org.apache.catalina.session.StandardSession in [Profiler]-[Memory settings]. But it shows only the size of StandardSession itself (the size of ConcurrentHashMap contained in StandardSession is not included).
  • I have profiled the application with Flight Recorder and viewed the result with Mission Control. But I cannot find out which objects are referenced from HttpSession.
  • You can list all HttpSession with org.apache.catalina.session.ManagerBase#findSessions() and measure the size of HttpSessions with Byteman and SizeOf.deepSizeOf(). But this Byteman rule runs only when a new HttpSession is created. I want measure memory consumption with HttpSessions at an arbitrary point in time (e.g. in every 30 seconds).

Advertisement

Answer

According to the comment from @LMC, I made a sample project to get the size of HttpSession with JMX: https://github.com/satob/SessionSize

Note that because you cannot access org.apache.catalina.session.ManagerBase directly, this project uses ByteMan. Store the ManagerBase object to a static field of the MBean SessionMonitor with Byteman like:

RULE Set ManagerBase object to MBean
CLASS ^org.apache.catalina.session.ManagerBase
METHOD initInternal
AT EXIT
IF TRUE
DO
    traceln("SETTING SessionManager");
    com.example.sessionsize.SessionMonitor.setSessionManager($this);
ENDRULE

and use it in the JMX interface like:

package com.example.sessionsize;

import org.apache.catalina.Manager;
import org.apache.catalina.Session;

import net.sourceforge.sizeof.SizeOf;

public class SessionMonitor implements SessionMonitorMBean {

    private static Manager sessionManager = null;

    public static void setSessionManager(Manager manager) {
        sessionManager = manager;
    }

    @Override
    public long getMemoryConsumption() {
        if (sessionManager != null) {
            try {
                Session [] sessions = sessionManager.findSessions();
                return SizeOf.deepSizeOf(sessions);
            } catch(RuntimeException e) {
                // Falied to get size of HttpSession object
                e.printStackTrace();
                return -2;
            }
        } else {
            // SessionManager is not ready
            return -1;
        }
    }

    @Override
    public long getNumberOfActiveHttpSession() {
        return sessionManager.findSessions().length;
    }
}

enter image description here

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement