Monitoring HttpSession memory leak during JavaEE development
October 2, 2014 Leave a comment
In my previous post I have provided a sample servlet filter to monitor non-serializable objects in HttpSession to make the JavaEE application compatible for clustered environment. We have enhanced the same servlet filter to log HttpSession object size which is helping us to find the memory leak during the development.
Here is the Java code
package org.webmoli.servlets; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.Enumeration; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class HttpSessionFilter implements Filter { private boolean testSerializability; @Override public void init(FilterConfig filterConfig) throws ServletException { testSerializability = Boolean.valueOf(filterConfig.getInitParameter("testSerializability")); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); // this block of code ensures all the values in the HttpSession object are serializable to ensure it works on // clustered environment if (testSerializability) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpSession httpSession = httpServletRequest.getSession(false); if (httpSession != null) { Enumeration<?> enumeration = httpSession.getAttributeNames(); int totalSize = 0; while (enumeration.hasMoreElements()) { Object value = httpSession.getAttribute((String) enumeration.nextElement()); if (value != null) { try { totalSize = totalSize + sizeof(value); } catch (Exception exp) { exp.printStackTrace(); throw new RuntimeException(exp.getMessage()); } } } System.out.println(String.format("Size of the session object is: %d KB", +(totalSize * 1f / 1024))); } } } @Override public void destroy() { } public static int sizeof(Object obj) throws IOException { ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream); objectOutputStream.writeObject(obj); objectOutputStream.flush(); objectOutputStream.close(); return byteOutputStream.toByteArray().length; } }
The web.xml entry looks like below.
<filter> <filter-name>HttpSessionFilter</filter-name> <filter-class>org.webmoli.servlets.HttpSessionFilter</filter-class> <init-param> <param-name>testSerializability</param-name> <!-- Make the below value as false in production environment --> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>HttpSessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>