Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Won't Fix
-
Affects Version/s: 1.7.1
-
Fix Version/s: 1.8RC1
-
Component/s: ICE-Components
-
Labels:None
-
Environment:Facelets and a variety of webservers
-
Support Case References:
Description
Customer has a large Facelets based application based around a single large interface page with a large number of Panel components and UI:include tags. The nature of the application is slightly different from the facelets component-showcase application such that it is possible to detect in component-showcase, but isn't of the same magnitude.
Long term use of the application finds memory accumulating in a HashMap, owned by DefaultFaceletFactory, referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class.
Long term use of the application finds memory accumulating in a HashMap, owned by DefaultFaceletFactory, referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class.
Issue Links
- blocks
-
ICE-3083 Memory performance/efficiency
- Open
Activity
Greg Dick
created issue -
Michael Thiem
made changes -
Field | Original Value | New Value |
---|---|---|
Support Case References | https://www.icesoft.ca:4443/supportilla/show_bug.cgi?id=4899 |
Ken Fyten
made changes -
Fix Version/s | 1.7.2 [ 10130 ] | |
Assignee | Deryk Sinotte [ deryk.sinotte ] |
Ken Fyten
made changes -
Assignee Priority | P2 | |
Assignee | Deryk Sinotte [ deryk.sinotte ] | Mark Collette [ mark.collette ] |
Mark Collette
made changes -
Summary | Facelets application retains memory in operation | Facelets application retains HashMap of Facelet objects |
Description |
Customer has a large Facelets based application based around a single large interface page with a large number of Panel components and UI:include tags. The nature of the application is slightly different from the facelets component-showcase application such that it is possible to detect in component-showcase, but isn't of the same magnitude. Long term use of the application finds memory accumulating in a hashmap referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class. |
Customer has a large Facelets based application based around a single large interface page with a large number of Panel components and UI:include tags. The nature of the application is slightly different from the facelets component-showcase application such that it is possible to detect in component-showcase, but isn't of the same magnitude. Long term use of the application finds memory accumulating in a HashMap referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class. |
Mark Collette
made changes -
Description |
Customer has a large Facelets based application based around a single large interface page with a large number of Panel components and UI:include tags. The nature of the application is slightly different from the facelets component-showcase application such that it is possible to detect in component-showcase, but isn't of the same magnitude. Long term use of the application finds memory accumulating in a HashMap referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class. |
Customer has a large Facelets based application based around a single large interface page with a large number of Panel components and UI:include tags. The nature of the application is slightly different from the facelets component-showcase application such that it is possible to detect in component-showcase, but isn't of the same magnitude. Long term use of the application finds memory accumulating in a HashMap, owned by DefaultFaceletFactory, referenced by D2DFaceletsViewHandler. When the user logs out, not all of the memory is released by this class. |
Ken Fyten
made changes -
Comment |
[ I'd like to confirm that this is indeed a bug. Facelet's Refresh period has nothing to do with it. There seems to be a number of problems with the way icefaces handles View class instances I've only been looking at the code for a day or so, but here are some observations: 1. MultiviewServer.service() implementation is getting called more than once for the same view browser view. As a result MultiviewServer.views map ends up holding stale View instances. This is because of the following observation: As far as I understand the DisposeViews.service() will only be called with view ids (value of context variable ice.view) that are known to the JS client side. I observed that '.../dispose-views' context is only called with the latest ice-view id. Do you guys map ice-view value to a resource conext, say ice-view maps to ../context/resource.iface? I'm continuing to investigate but I can clearly see that MultiviewServer.views, which is a reference to MainSessionBoundServlet.views map grows unbounded. Please understand that this is a *very large* memory loss. Because View.java holds to the UIViewRoot which represents all of UI component hierarchy. Using facelets and facelets include directive application gets components for *all* screens parsed and stored in component hierarchy. So the leaks can be in *megabites* per lost instance of View. 2. MultiviewServer.service() call to server.service(request) can and does throw exceptions which are not handled. However the view map is already populated with a new view, but the exception is propagated back to the client. I suspect the ice-view id never gets to the client, hence we get another case of stale View instance 3. View instances *can and will* take up a lot of resources. I guess you're keeping those views around for performance reasons, but if there are a lot of UIComponents in the application then JVM will and does poop rather quickly. Can you use a configurable LRU strategy and blow unused views away? And here is the exception that I get that caused memory bloat because of point 2. Best. Jul 10, 2008 10:03:55 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet jsp threw exception java.net.SocketException: Broken pipe at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) at java.net.SocketOutputStream.write(SocketOutputStream.java:136) at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:737) at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434) at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:349) at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:761) at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:126) at org.apache.coyote.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:570) at org.apache.coyote.Response.doWrite(Response.java:560) at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:353) at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:325) at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:381) at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:370) at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:89) at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:336) at sun.nio.cs.StreamEncoder$CharsetSE.implWrite(StreamEncoder.java:395) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:136) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:146) at java.io.OutputStreamWriter.write(OutputStreamWriter.java:204) at java.io.Writer.write(Writer.java:126) at com.icesoft.faces.context.NormalModeSerializer.serialize(NormalModeSerializer.java:60) at com.icesoft.faces.context.DOMResponseWriter.endDocument(DOMResponseWriter.java:137) at com.icesoft.faces.facelets.D2DFaceletViewHandler.renderResponse(D2DFaceletViewHandler.java:283) at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:161) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:108) at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:266) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:159) at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:18) at com.icesoft.faces.webapp.http.core.PageServer$1.respond(PageServer.java:25) at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:161) at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet$ThreadBlockingRequestResponse.respondWith(ThreadBlockingAdaptingServlet.java:36) at com.icesoft.faces.webapp.http.core.PageServer.service(PageServer.java:30) at com.icesoft.faces.webapp.http.core.MultiViewServer.service(MultiViewServer.java:57) at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer$Matcher.serviceOnMatch(PathDispatcherServer.java:50) at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:19) at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet.service(ThreadBlockingAdaptingServlet.java:19) at com.icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63) at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:139) at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:53) at com.icesoft.faces.webapp.http.servlet.PathDispatcher$Matcher.serviceOnMatch(PathDispatcher.java:52) at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:29) at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:82) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630) at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436) at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374) at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302) at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:694) at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:665) at org.apache.jsp.index_jsp._jspService(index_jsp.java:57) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:595) ] |
Ken Fyten
made changes -
Comment | [ I think the reason I'm seing multiple View instances created for the same browser view (actual window) is because I have concurrentDOMViews = true. But I'd expect that this call flow will happen when I acutally have a new tab/browser window on the same box sending requests to the same server context. However I'm seeing this flow when I generate UI events on the same window. This leads to stale Views as I mentioned earlier ] |
Ken Fyten
made changes -
Comment | [ There seem to be a race condition on the client (js) side of things. If I break point in FireBug on js callbacks that handle server replies I never see the exception reported above (Broken Pipe). ] |
Ken Fyten
made changes -
Assignee Priority | P2 | P1 |
Ken Fyten
made changes -
Assignee Priority | P1 |
Ken Fyten
made changes -
Fix Version/s | 1.8DR#2 [ 10142 ] | |
Fix Version/s | 1.7.2 [ 10130 ] |
Ken Fyten
made changes -
Fix Version/s | 1.8DR#3 [ 10143 ] | |
Fix Version/s | 1.8DR#2 [ 10142 ] |
Mark Collette
made changes -
Status | Open [ 1 ] | Closed [ 6 ] |
Resolution | Won't Fix [ 2 ] |
From Mark C. message #1
I remember reading about this on the Facelets mailing list. Basically, DefaultFaceletFactory, which extends FaceletFactory, does all of the parsing of the .xhtml files into Facelet objects, and also caches them. But there's no actual limit on the cache. The good news is that it's bounded by the number of .xhtml files, so it won't leak forever, unless they're auto-generating .xhtml files.
Here's my message, quoting the original one:
https://facelets.dev.java.net/servlets/ReadMsg?list=users&msgNo=8882
And here's the bugzilla entry someone made for it:
https://facelets.dev.java.net/issues/show_bug.cgi?id=260
And more importantly, From Mark message #2
The [D2D]FaceletViewHandler owns the DefaultFaceletFactory, so all users would be sharing the same cache of Facelet objects, since I believe all requests in an application share the same ViewHandler.
But, what could explain the continuous leaking of HashMap entry objects, is if the Facelet refreshing is enabled. That's a mechanism typically used in development for rapid application development, and also in production to allow for changing content without having to restart the application. If it has a value of -1, then refreshing is disabled, and content is static, otherwise it's the number of seconds that a Facelet will be reused for, before reparsing it from the .xhtml file. The default value is 2. And 0 would effectively mean to always reparse. Small values like 2 are useful for debugging, but not production. Have them try -1, to see if the problem goes away. Afterwards they can tune it to whatever they like, if they want to be able to update pages on the go.
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>2</param-value>
</context-param>