You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by sk...@comcast.net on 2007/09/04 19:02:18 UTC

[jira] Created: (TOMAHAWK-1040) Apparent File Handle Leak with Tomahawk 1.1.5 or 1.1.6 with MyFaces 1.1.5

Derek,

We just started seeing our Web application hanging this last week to too many open files (Switched over to tomahawk 1.1.5 about two weeks ago and use both the calendar function and the JSCookMenu).  I saw your post here and was wondering two things.  First, do you know if the new version of MyFaces 1.2.0 has fixed this issue?  Second,  where in the configuration do you make the change to call the new resource class instead of the DefaultAddResource? 

Thanks,

Randy Skold


My Faces - Dev mailing list wrote:
> 
> Apparent File Handle Leak with Tomahawk 1.1.5 or 1.1.6 with MyFaces 1.1.5
> -------------------------------------------------------------------------
> 
>                  Key: TOMAHAWK-1040
>                  URL: https://issues.apache.org/jira/browse/TOMAHAWK-1040
>              Project: MyFaces Tomahawk
>           Issue Type: Bug
>     Affects Versions: 1.1.6, 1.1.5
>          Environment: Linux version 2.6.9-42.0.10.plus.c4smp
> Java 1.5.0_09-b03
> Tomcat 5.5.20
> 
>             Reporter: Derek C. Ashmore
>             Priority: Critical
> 
> 
> We experienced a file handle leak when using Tomahawk components that
> require static resources, such as the JSCookMenu, Calendar, and Tabbed
> Pane.  The handle allocations never go away.  Eventually, the container
> becomes inoperative and has to be restarted.
> 
> We experience this bug under Tomahawk 1.1.5 and 1.1.6 using Myfaces 1.1.5. 
> We do *not* experience the leak under Myfaces/Tomahawk 1.1.3.  I have no
> information about whether the bug appears under 1.1.4.
> 
> We detected the leak behavior by monitoring our container process using
> lsof.
> 
> Although it's a hack and I don't like it, I was able to avoid the leak by
> writing a custom AddResource class (and changing the configuration so that
> my custom class was used instead of the default).  My custom AddResource
> class works by caching request resources and preventing more than one I/O
> to a given resource.
> 
> My source code (for what it's worth) is attached below.  I'd be happy to
> provide additional information -- I would rather see this bug fixed in
> 1.1.6 then have my hack around for ever.
> 
> Thanks for looking at this.
> 
> ---------------------------------------------------------------------------------------------------------
> package com.ies.common.ui.common.util;
> 
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.util.Map;
> import java.util.StringTokenizer;
> import java.util.concurrent.ConcurrentHashMap;
> 
> import javax.servlet.ServletContext;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> 
> import org.apache.myfaces.renderkit.html.util.DefaultAddResource;
> import org.apache.myfaces.renderkit.html.util.DefaultResourceProvider;
> import org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader;
> 
> import com.ies.common.error.IESRuntimeException;
> 
> /**
>  * Needed to prevent 'too many file handles' problem.
>  * @author D. Ashmore
>  *
>  */
> public class IesAddResource extends DefaultAddResource {
> 	
> 	private static final String MYFACES_RESOURCE = "MyFacesResourceLoader";
> 	private static final String MYFACES_PACKAGE_PREFIX =
> "org.apache.myfaces.custom.";
> 	private static Map<String, Resource> resourceMap = new
> ConcurrentHashMap<String, Resource>();
> 
> 	public IesAddResource() {
> 		// No Op
> 	}
> 
> 	@Override
> 	public void serveResource(ServletContext context, HttpServletRequest
> request, HttpServletResponse response) throws IOException {
> 		String pathInfo = request.getPathInfo();
>         String uri = request.getContextPath() + request.getServletPath()
>                 + (pathInfo == null ? "" : pathInfo);
>         
>         if (uri.indexOf(MYFACES_RESOURCE) > 0) {
>         	StringTokenizer token = new StringTokenizer(uri, "/");
>         	if (token.countTokens() < 6) {
>         		super.serveResource(context, request, response);
>         		return;
>         	}
>         	
>         	// Bypass the first five tokens as non-essential.
>         	token.nextToken();
>         	token.nextToken();
>         	token.nextToken();
>         	token.nextToken();
>         	token.nextToken();
>         	String className = token.nextToken();
>         	Class componentClass = null;
>         	try {
>         		componentClass = Class.forName(MYFACES_PACKAGE_PREFIX +
> className);
>         	}
>         	catch (Exception e) {
>         		IESRuntimeException ire = new IESRuntimeException("Class not
> found.");
> 				ire.addLabeledValue("className", className);
> 				
> 				throw ire;
>         	}
>         	
>         	DefaultResourceProvider provider = new
> DefaultResourceProvider(componentClass);
>         	String resource = uri.substring(
>         			uri.lastIndexOf(className) + 
>         			className.length() + 1);
>         	String resourceKey = className + resource;
>         	
>         	Resource resourceData = (Resource)resourceMap.get(resourceKey);
>         	InputStream is = null;
>         	MyResourceLoader loader = new MyResourceLoader();
>         	
>         	if (resourceData == null) {    	
>         		resourceData = new Resource();
>         		try {
>         			is = provider.getInputStream(context, resource);
>         			if (is == null) {
>         				IESRuntimeException ire = new IESRuntimeException("Resource
> not found.");
>         				ire.addLabeledValue("resource", resource);
>         				
>         				throw ire;
>         			}
>         			resourceData.setData(inputStreamReader(is));
>         			resourceData.setEncoding(provider.getEncoding(context,
> resource));
>         			resourceData.setLastModified(provider.getLastModified(context,
> resource));
>         		
> resourceData.setContentLength(provider.getContentLength(context,
> resource));
>         		}
>         		finally {if (is != null) is.close();}
>         		resourceMap.put(resourceKey, resourceData);
> 
>         	}
>         	is = new ByteArrayInputStream(resourceData.data);
>         	
>         	loader.defineContentHeaders(request, response, resource,
> resourceData.data.length, resourceData.encoding);
>         	loader.defineCaching(request, response, resource,
> resourceData.lastModified);
>         	loader.writeResource(request, response, is);
>         }
>         else super.serveResource(context, request, response);
> 	}
> 	
> 	private byte[] inputStreamReader(InputStream is) throws IOException {
> 		ByteArrayOutputStream outStream = new ByteArrayOutputStream(512000);
> 		
> 		byte[] bArray = new byte[8192];
> 		int nbrBytesRead = is.read(bArray);
> 		while (nbrBytesRead > 0) {
> 			outStream.write(bArray, 0, nbrBytesRead);
> 			nbrBytesRead = is.read(bArray);
> 		}
> 		
> 		return outStream.toByteArray();
> 	}
> 	
> 	private static class Resource {
> 		byte[] data;
> 		long lastModified;
> 		long contentLength;
> 		String encoding;
> 		
> 		public Resource() {
> 		}
> 
> 		public byte[] getData() {
> 			return data;
> 		}
> 
> 		public void setData(byte[] data) {
> 			this.data = data;
> 		}
> 
> 		public String getEncoding() {
> 			return encoding;
> 		}
> 
> 		public void setEncoding(String encoding) {
> 			this.encoding = encoding;
> 		}
> 
> 		public long getLastModified() {
> 			return lastModified;
> 		}
> 
> 		public void setLastModified(long lastModified) {
> 			this.lastModified = lastModified;
> 		}
> 
> 		public long getContentLength() {
> 			return contentLength;
> 		}
> 
> 		public void setContentLength(long contentLength) {
> 			this.contentLength = contentLength;
> 		}
> 	}
> 	
> 	private static class MyResourceLoader extends MyFacesResourceLoader {
> 
> 		@Override
> 		public void defineCaching(HttpServletRequest request,
> HttpServletResponse response, String resource, long lastModified) {
> 			super.defineCaching(request, response, resource, lastModified);
> 		}
> 
> 		@Override
> 		public void defineContentHeaders(HttpServletRequest request,
> HttpServletResponse response, String resource, int contentLength, String
> contentEncoding) {
> 			super.defineContentHeaders(request, response, resource, contentLength,
> 					contentEncoding);
> 		}
> 
> 		@Override
> 		public void writeResource(HttpServletRequest request,
> HttpServletResponse response, InputStream in) throws IOException {
> 			super.writeResource(request, response, in);
> 		}
> 		
> 	}
> 
> }
> 
> -- 
> This message is automatically generated by JIRA.
> -
> You can reply to this email to add a comment to the issue online.
> 
> 
> 
Quoted from: 
http://www.nabble.com/-jira--Created%3A-%28TOMAHAWK-1040%29-Apparent-File-Handle-Leak-with-Tomahawk-1.1.5-or-1.1.6-with-MyFaces-1.1.5-tf3998086.html#a11354721


Re: [jira] Created: (TOMAHAWK-1040) Apparent File Handle Leak with Tomahawk 1.1.5 or 1.1.6 with MyFaces 1.1.5

Posted by Andrew Robinson <an...@gmail.com>.
I am getting this error in MyFaces 1.1.5 / Tomahawk 1.1.7-SNAPSHOT. I
am not using JSCookMenu, Calendar or the TabbedPane. If I get it again
I will see if I can get more information on this.

The tomahawk/sandbox components that I am using mostly are
panelNavigation2, focus, roundedDiv and messages.

-Andrew

On 9/4/07, skold@comcast.net <sk...@comcast.net> wrote:
> Derek,
>
> We just started seeing our Web application hanging this last week to too many open files (Switched over to tomahawk 1.1.5 about two weeks ago and use both the calendar function and the JSCookMenu).  I saw your post here and was wondering two things.  First, do you know if the new version of MyFaces 1.2.0 has fixed this issue?  Second,  where in the configuration do you make the change to call the new resource class instead of the DefaultAddResource?
>
> Thanks,
>
> Randy Skold
>
>
> My Faces - Dev mailing list wrote:
> >
> > Apparent File Handle Leak with Tomahawk 1.1.5 or 1.1.6 with MyFaces 1.1.5
> > -------------------------------------------------------------------------
> >
> >                  Key: TOMAHAWK-1040
> >                  URL: https://issues.apache.org/jira/browse/TOMAHAWK-1040
> >              Project: MyFaces Tomahawk
> >           Issue Type: Bug
> >     Affects Versions: 1.1.6, 1.1.5
> >          Environment: Linux version 2.6.9-42.0.10.plus.c4smp
> > Java 1.5.0_09-b03
> > Tomcat 5.5.20
> >
> >             Reporter: Derek C. Ashmore
> >             Priority: Critical
> >
> >
> > We experienced a file handle leak when using Tomahawk components that
> > require static resources, such as the JSCookMenu, Calendar, and Tabbed
> > Pane.  The handle allocations never go away.  Eventually, the container
> > becomes inoperative and has to be restarted.
> >
> > We experience this bug under Tomahawk 1.1.5 and 1.1.6 using Myfaces 1.1.5.
> > We do *not* experience the leak under Myfaces/Tomahawk 1.1.3.  I have no
> > information about whether the bug appears under 1.1.4.
> >
> > We detected the leak behavior by monitoring our container process using
> > lsof.
> >
> > Although it's a hack and I don't like it, I was able to avoid the leak by
> > writing a custom AddResource class (and changing the configuration so that
> > my custom class was used instead of the default).  My custom AddResource
> > class works by caching request resources and preventing more than one I/O
> > to a given resource.
> >
> > My source code (for what it's worth) is attached below.  I'd be happy to
> > provide additional information -- I would rather see this bug fixed in
> > 1.1.6 then have my hack around for ever.
> >
> > Thanks for looking at this.
> >
> > ---------------------------------------------------------------------------------------------------------
> > package com.ies.common.ui.common.util;
> >
> > import java.io.ByteArrayInputStream;
> > import java.io.ByteArrayOutputStream;
> > import java.io.IOException;
> > import java.io.InputStream;
> > import java.util.Map;
> > import java.util.StringTokenizer;
> > import java.util.concurrent.ConcurrentHashMap;
> >
> > import javax.servlet.ServletContext;
> > import javax.servlet.http.HttpServletRequest;
> > import javax.servlet.http.HttpServletResponse;
> >
> > import org.apache.myfaces.renderkit.html.util.DefaultAddResource;
> > import org.apache.myfaces.renderkit.html.util.DefaultResourceProvider;
> > import org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader;
> >
> > import com.ies.common.error.IESRuntimeException;
> >
> > /**
> >  * Needed to prevent 'too many file handles' problem.
> >  * @author D. Ashmore
> >  *
> >  */
> > public class IesAddResource extends DefaultAddResource {
> >
> >       private static final String MYFACES_RESOURCE = "MyFacesResourceLoader";
> >       private static final String MYFACES_PACKAGE_PREFIX =
> > "org.apache.myfaces.custom.";
> >       private static Map<String, Resource> resourceMap = new
> > ConcurrentHashMap<String, Resource>();
> >
> >       public IesAddResource() {
> >               // No Op
> >       }
> >
> >       @Override
> >       public void serveResource(ServletContext context, HttpServletRequest
> > request, HttpServletResponse response) throws IOException {
> >               String pathInfo = request.getPathInfo();
> >         String uri = request.getContextPath() + request.getServletPath()
> >                 + (pathInfo == null ? "" : pathInfo);
> >
> >         if (uri.indexOf(MYFACES_RESOURCE) > 0) {
> >               StringTokenizer token = new StringTokenizer(uri, "/");
> >               if (token.countTokens() < 6) {
> >                       super.serveResource(context, request, response);
> >                       return;
> >               }
> >
> >               // Bypass the first five tokens as non-essential.
> >               token.nextToken();
> >               token.nextToken();
> >               token.nextToken();
> >               token.nextToken();
> >               token.nextToken();
> >               String className = token.nextToken();
> >               Class componentClass = null;
> >               try {
> >                       componentClass = Class.forName(MYFACES_PACKAGE_PREFIX +
> > className);
> >               }
> >               catch (Exception e) {
> >                       IESRuntimeException ire = new IESRuntimeException("Class not
> > found.");
> >                               ire.addLabeledValue("className", className);
> >
> >                               throw ire;
> >               }
> >
> >               DefaultResourceProvider provider = new
> > DefaultResourceProvider(componentClass);
> >               String resource = uri.substring(
> >                               uri.lastIndexOf(className) +
> >                               className.length() + 1);
> >               String resourceKey = className + resource;
> >
> >               Resource resourceData = (Resource)resourceMap.get(resourceKey);
> >               InputStream is = null;
> >               MyResourceLoader loader = new MyResourceLoader();
> >
> >               if (resourceData == null) {
> >                       resourceData = new Resource();
> >                       try {
> >                               is = provider.getInputStream(context, resource);
> >                               if (is == null) {
> >                                       IESRuntimeException ire = new IESRuntimeException("Resource
> > not found.");
> >                                       ire.addLabeledValue("resource", resource);
> >
> >                                       throw ire;
> >                               }
> >                               resourceData.setData(inputStreamReader(is));
> >                               resourceData.setEncoding(provider.getEncoding(context,
> > resource));
> >                               resourceData.setLastModified(provider.getLastModified(context,
> > resource));
> >
> > resourceData.setContentLength(provider.getContentLength(context,
> > resource));
> >                       }
> >                       finally {if (is != null) is.close();}
> >                       resourceMap.put(resourceKey, resourceData);
> >
> >               }
> >               is = new ByteArrayInputStream(resourceData.data);
> >
> >               loader.defineContentHeaders(request, response, resource,
> > resourceData.data.length, resourceData.encoding);
> >               loader.defineCaching(request, response, resource,
> > resourceData.lastModified);
> >               loader.writeResource(request, response, is);
> >         }
> >         else super.serveResource(context, request, response);
> >       }
> >
> >       private byte[] inputStreamReader(InputStream is) throws IOException {
> >               ByteArrayOutputStream outStream = new ByteArrayOutputStream(512000);
> >
> >               byte[] bArray = new byte[8192];
> >               int nbrBytesRead = is.read(bArray);
> >               while (nbrBytesRead > 0) {
> >                       outStream.write(bArray, 0, nbrBytesRead);
> >                       nbrBytesRead = is.read(bArray);
> >               }
> >
> >               return outStream.toByteArray();
> >       }
> >
> >       private static class Resource {
> >               byte[] data;
> >               long lastModified;
> >               long contentLength;
> >               String encoding;
> >
> >               public Resource() {
> >               }
> >
> >               public byte[] getData() {
> >                       return data;
> >               }
> >
> >               public void setData(byte[] data) {
> >                       this.data = data;
> >               }
> >
> >               public String getEncoding() {
> >                       return encoding;
> >               }
> >
> >               public void setEncoding(String encoding) {
> >                       this.encoding = encoding;
> >               }
> >
> >               public long getLastModified() {
> >                       return lastModified;
> >               }
> >
> >               public void setLastModified(long lastModified) {
> >                       this.lastModified = lastModified;
> >               }
> >
> >               public long getContentLength() {
> >                       return contentLength;
> >               }
> >
> >               public void setContentLength(long contentLength) {
> >                       this.contentLength = contentLength;
> >               }
> >       }
> >
> >       private static class MyResourceLoader extends MyFacesResourceLoader {
> >
> >               @Override
> >               public void defineCaching(HttpServletRequest request,
> > HttpServletResponse response, String resource, long lastModified) {
> >                       super.defineCaching(request, response, resource, lastModified);
> >               }
> >
> >               @Override
> >               public void defineContentHeaders(HttpServletRequest request,
> > HttpServletResponse response, String resource, int contentLength, String
> > contentEncoding) {
> >                       super.defineContentHeaders(request, response, resource, contentLength,
> >                                       contentEncoding);
> >               }
> >
> >               @Override
> >               public void writeResource(HttpServletRequest request,
> > HttpServletResponse response, InputStream in) throws IOException {
> >                       super.writeResource(request, response, in);
> >               }
> >
> >       }
> >
> > }
> >
> > --
> > This message is automatically generated by JIRA.
> > -
> > You can reply to this email to add a comment to the issue online.
> >
> >
> >
> Quoted from:
> http://www.nabble.com/-jira--Created%3A-%28TOMAHAWK-1040%29-Apparent-File-Handle-Leak-with-Tomahawk-1.1.5-or-1.1.6-with-MyFaces-1.1.5-tf3998086.html#a11354721
>
>