【问题标题】:Stuck thread at popComponentFromEL(UIComponent.java:2084) causing high cpu usage卡在 popComponentFromEL(UIComponent.java:2084) 的线程导致 CPU 使用率高
【发布时间】:2020-03-07 20:29:58
【问题描述】:

我们在项目中使用动态绑定组件。

由于 UIComponent.popComponentFromEL (UIComponent.java:2084) 处有多个卡住线程而导致 CPU 使用率过高 每个线程在 UIComponent.java 的第 2084 行引用相同的行号。这里是线程转储的 sn-p。

javax.faces.component.UIComponent.popComponentFromEL(UIComponent.java:2084)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2326)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.publishAfterViewEvents(UIComponentBase.java:2314)
javax.faces.component.UIComponentBase.doPostAddProcessing(UIComponentBase.java:1986)
javax.faces.component.UIComponentBase.setParent(UIComponentBase.java:459)
javax.faces.component.UIComponentBase$ChildrenList.add(UIComponentBase.java:2772)
javax.faces.component.UIComponentBase$ChildrenList.add(UIComponentBase.java:2742)
com.sun.faces.facelets.tag.jsf.ComponentSupport.addComponent(ComponentSupport.java:527)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.addComponentToView(ComponentTagHandlerDelegateImpl.java:354)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.addComponentToView(ComponentTagHandlerDelegateImpl.java:337)
com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:222)
javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:135)
javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:96)
com.sun.faces.facelets.tag.jsf.core.ViewHandler.apply(ViewHandler.java:224)
javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:96)
com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:94)
com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:88)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:313)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:372)
com.sun.faces.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:351)
com.sun.faces.facelets.impl.DefaultFaceletContext.includeFacelet(DefaultFaceletContext.java:204)
com.sun.faces.facelets.tag.ui.CompositionHandler.apply(CompositionHandler.java:175)
com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:94)
com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:88)
com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:162)
com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:381)
com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:289)
com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:157)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.restoreView(PrettyViewHandler.java:109)
com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:204)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:133)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:201)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:670)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:470)
org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:137)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)

我尝试了以下答案中提供的解决方案,但有很多页面我们已经实现了组件绑定,并且不可能更改每个页面的范围。 Stuck thread at UIComponent.popComponentFromEL 我从UIComponent.java 文件中删除了以下代码,它似乎正在工作。 这是full code file

for (UIComponent topComponent = componentELStack.peek();
     topComponent != this;
     topComponent = componentELStack.peek())
{
   topComponent.popComponentFromEL(context);
}

有人可以详细说明topComponent.popComponentFromEL(context); 的目的是什么 如果我评论该代码,那会有什么副作用?

根据 JSF 表单/GitHub 问题跟踪器建议,我还在 web.xml 中添加了 SERIALIZE_SERVER_STATE 参数,但没有运气。

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

另外,尝试更改 JSF 版本 2.2 仍然存在问题

环境:

  1. Mojarra JSF 2.3.2
  2. Java 8
  3. Primefaces 6.1
  4. Tomcat 8.5

【问题讨论】:

  • 你能添加你明确的 Mojarra 版本吗? 'JSF 2.3' 只是一个 api 版本
  • 显式版本是 JSF 2.3.2 @Kukeltje
  • Mojarra、MyFaces 或 JSF 2.3.2 API 的其他实现?
  • 我们正在使用 Mojarra 实现 @Selaron
  • @Selaron:Mojarra 可能已经从堆栈跟踪中扣除了... Divyesh:我希望 BalusC(请求帮助不是“赞赏”顺便说一句)不明确说明删除此代码是好还是坏坏的。代码存在是有原因的,因此在某些情况下删除可能会导致其他不清楚的问题。我希望他能说出其他 Q/A 中已经说明的内容来纠正问题:“相应地修复代码,使这种情况永远不会发生。组件本质上是请求范围的,并且绝对不能在多个请求之间共享。”

标签: multithreading jsf binding


【解决方案1】:

我从UIComponent.java 文件中删除了以下代码,它似乎可以正常工作。这是代码sn-p:

for (UIComponent topComponent = componentELStack.peek();
     topComponent != this;
     topComponent = componentELStack.peek())
{
   topComponent.popComponentFromEL(context);
}

有人可以详细说明topComponent.popComponentFromEL(context); 的用途是什么,如果我删除该代码,会有什么副作用?

这段代码基本上管理了JSF页面中隐含的EL表达式#{component}。删除它会影响#{component} 在EL 中的行为。例如,在以下构造中,

<h:someComponent id="foo">
    <h:someComponent id="bar" />
    #{component}
</h:someComponent>

...预期的行为是#{component} 会给你id="foo"。但是随着您的更改,它会错误地为您提供id="bar"


根据 JSF 表单/GitHub 问题跟踪器建议,我还在 web.xml 中添加了 SERIALIZE_SERVER_STATE 参数,但没有运气。

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

当您将组件绑定分配给 transient 属性时,这将不起作用。即使你解决了这个问题,这仍然不能真正“解决”你的问题。它只会在更快的时刻抛出NotSerializableException。当您刚刚打开 JSF 页面时,当多个用户打开 JSF 页面时,您将面临“卡住线程”错误。 NotSerializableException 应该向开发人员发出明确的警告,即开发人员正在做一些完全错误的事情。


另外,尝试更改 JSF 2.2 版仍然存在问题

您遇到的问题不是特定于 JSF 版本的问题。这是开发人员的错误。只需从不UIComponent 分配为比@RequestScoped 范围更广的托管bean 的属性。另见How does the 'binding' attribute work in JSF? When and how should it be used?

只需通过从UIComponent.java 中删除这段代码来解决问题。您仍将拥有一个非线程安全的 JSF Web 应用程序。当用户 X 修改特定组件的一个属性时,例如disabled 变为 true,然后它也会影响所有其他用户,这最终会导致 web 应用程序无法运行。

【讨论】:

  • 感谢详细的补偿,因为我们观察到for loop 递归调用而不是中断。 github.com/eclipse-ee4j/mojarra/issues/…您对此修复有何看法?
  • 我不同意这一点。它基本上隐藏了一个主要的潜在问题:非线程安全的 webapp。你不应该试图通过覆盖/抑制/隐藏它可能导致的所有可能的异常来解决这个问题,不。您应该尝试通过其根本问题来解决这个问题:永远不要将组件绑定到不在请求范围内的 bean。然后它所有可能的后果/异常将简单地自行解决,你最终会得到一个线程安全的 webapp。这就是您和您的公司最终想要的,对吧?
  • 当我们使用视图范围时,是否有组件绑定的替代方案?因为当我们使用请求范围时,需要进行大量代码重构。
  • 是的。我已经在我的回答中提到的“另见”链接中解释了所有替代方案。您绝对不需要迁移所有 bean 的范围。您只需迁移所有 binding 使用情况。很多时候,它根本不需要。
  • 感谢您对此的看法。我会看看你的解决方案。
猜你喜欢
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多