JSF 内存溢出

4

我正在使用PrimeFaces 5.3、JSF 2.2和Omnifaces 2.3创建一个应用程序。

我正在使用jdk v8、Glassfish 4.1.1和MySQL 5。

为了从安全角度提供更多信息,我正在使用OWASP ZAP应用程序。

问题是我遇到了一些“内存不足-JavaHeapSpace”问题。

  Avvertenza:   #{detailsController.loadDetail}: java.lang.OutOfMemoryError: Java heap space
  javax.faces.FacesException: #{detailsController.loadDetail}: java.lang.OutOfMemoryError: Java heap space
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
    at javax.faces.component.UIViewAction.broadcast(UIViewAction.java:562)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.glassfish.tyrus.servlet.TyrusServletFilter.doFilter(TyrusServletFilter.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at com.classicvirus.jsf.LoggedUserWebFilter.doFilter(LoggedUserWebFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)
  Caused by: javax.faces.el.EvaluationException: java.lang.OutOfMemoryError: Java heap space
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    ... 46 more
  Caused by: java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
    at org.hibernate.type.descriptor.java.DataHelper.extractBytes(DataHelper.java:170)
    at org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor.wrap(PrimitiveByteArrayTypeDescriptor.java:108)
    at org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor.wrap(PrimitiveByteArrayTypeDescriptor.java:25)
    at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$1.doExtract(BlobTypeDescriptor.java:48)
    at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:235)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:231)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:222)
    at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:296)
    at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2762)
    at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.loadFromResultSet(EntityReferenceInitializerImpl.java:307)
    at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.hydrateEntityState(EntityReferenceInitializerImpl.java:235)
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:103)
    at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:238)
    at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:112)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
    at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
    at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3991)
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1142)
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1025)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:632)

如果我等待几分钟,就会看到这些日志

  WARN:   WELD-000714: HttpContextLifecycle guard leak detected. The Servlet container is not fully compliant. The value was 1
  WARN:   WELD-000225: Bean store leak was detected during org.jboss.weld.context.http.HttpRequestContextImpl association: org.apache.catalina.connector.RequestFacade@3a7067d8
  WARN:   WELD-000225: Bean store leak was detected during org.jboss.weld.context.http.HttpSessionContextImpl association: org.apache.catalina.connector.RequestFacade@3a7067d8
  WARN:   WELD-000335: Conversation context is already active, most likely it was not cleaned up properly during previous request processing: org.apache.catalina.connector.RequestFacade@3a7067d8
  Grave:   Unable to load class: 
  java.lang.OutOfMemoryError: GC overhead limit exceeded

  Avvertenza:   StandardWrapperValve[Faces Servlet]: Servlet.service() for servlet Faces Servlet threw exception
  java.lang.OutOfMemoryError: GC overhead limit exceeded

我的猜测与图像管理有关。我正在使用从数据库检索的图像,并采用我曾经看到过的facelets实现方法。

  <p:graphicImage value="#{applicationScopedBean.imagesFromDb}">
      <f:param name="imageId" value="#{actualAd.favouriteImageId}" />
      <f:param name="cvlTimeStamp" value="#{now}" />
  </p:graphicImage>

应用范围的 Bean
public StreamedContent getImagesFromDb() {
    FacesContext context = FacesContext.getCurrentInstance();

    if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
        return new DefaultStreamedContent();
    } else {
        String imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
        return new DefaultStreamedContent(new ByteArrayInputStream(advertisingImageManager.getById(Long.valueOf(imageId)).getContent()));
    }
}

我已经尝试了Omnifaces方法,但没有成功。 Facelets。
 <o:graphicImage value="#{applicationScopedBean.getImageById(actualAd.favouriteImageId)}" class="img" lastModified="#{now}"/>

应用程序作用域的bean

public byte[] getImageById(Long imageId){
    return advertisingImageManager.getById(imageId).getContent();
}

问题不是“我该如何解决这个问题”,而首先应该探究OWASP ZAP应用程序创建的这个问题是否正确。 如果是,我应该从哪里开始调查?

运行分析器。这是调查内存消耗的唯一方法。 - BalusC
1个回答

2
我使用了Netbeans内置的分析器。 我发现问题出在一个byte[]类型的字段上,它代表了一张图片。 在我的情况下,这个字段的大小是1.8Mb,而且在很多会话中,这种情况会导致内存不足错误。 通过将byte[]封装在一个新实体中并使用FetchMode.LAZY来解决此错误。

1
干得好。我只想指出,在<o:graphicImage>的文档中也提到了这一点。 - BalusC
1
是的,你说得对,我所有的疑虑都是因为我读了Omnifaces文档开始的。所以恭喜你们有如此清晰的文档。在我看来,它比人们想象的更有用,在“尝试”之前,我总是会阅读所有的文档,因为这样可以创造自己的知识。谢谢! - Gavi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接