我有一个承包商开发的Java应用程序来支持 - 我的经验主要是使用.NET,而且我无法访问任何知道应用程序代码的人。在Eclipse中的Tomcat服务器上运行时,此应用程序在我的开发环境中运行良好。但是,在将WAR部署到远程服务器(仍在开发环境中)之后,我得到了并发修改例外。我想在看到所有应用程序代码逐行检查之前,看看可能出现的原因。
我的理解是这个异常通常是通过修改迭代器对象来触发的,而你正在迭代它。但是为什么我在Eclipse中运行时没有得到异常?如果这肯定是代码中的错误,如果Eclipse没有触发异常,我如何找到它在代码中的位置?异常跟踪对我来说很模糊(粘贴在下面)。我看到的唯一文件引用是视图模板和。如果我必须依赖已部署的应用程序来调试,我如何找到代码中这个bug的位置?这可能是一个环境问题 - 如果是这样,可能导致什么?
Sep 6, 2016 3:50:57 PM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/views/editor.xhtml]
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
at java.util.LinkedHashMap$EntryIterator.next(Unknown Source)
at java.util.LinkedHashMap$EntryIterator.next(Unknown Source)
at java.util.AbstractMap.equals(Unknown Source)
at java.util.Collections$SynchronizedMap.equals(Unknown Source)
at com.sun.faces.context.SessionMap.put(SessionMap.java:138)
at com.sun.faces.context.SessionMap.put(SessionMap.java:61)
at com.sun.faces.renderkit.ServerSideStateHelper.writeState(ServerSideStateHelper.java:243)
at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122)
at com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:113)
at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:464)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:286)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1770)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
at java.util.LinkedHashMap$EntryIterator.next(Unknown Source)
at java.util.LinkedHashMap$EntryIterator.next(Unknown Source)
at java.util.AbstractMap.equals(Unknown Source)
at java.util.Collections$SynchronizedMap.equals(Unknown Source)
at com.sun.faces.context.SessionMap.put(SessionMap.java:138)
at com.sun.faces.context.SessionMap.put(SessionMap.java:61)
at com.sun.faces.renderkit.ServerSideStateHelper.writeState(ServerSideStateHelper.java:243)
at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122)
at com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:113)
at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:464)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:286)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1770)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:1)
由于stacktrace只显示内部API(Tomcat,JSF,JDK),因此很难得出任何结论。我们知道,ConcurrentModificationException
在我们迭代fail-fast
集合时发生,并且在迭代期间进行了修改。这可以从不同的线程发生,但同样容易从同一个线程发生。如果你不确定它是如何工作的,那么SO就是很多例子。
如果我们假设修改发生在同一个线程中,那么堆栈跟踪将显示罪魁祸首。在这种情况下,它将在com.sun.faces.context.SessionMap.put(SessionMap.java:138)附近。
基于代码(doSet = ! result.equals(value);
)和堆栈跟踪,它检查LinkedHashMap
到value
的相等性,我们可以从堆栈跟踪中看到它也是{{1} }。
但是,我们也可以看到LinkedHashMap
包含result
。这很重要,因为我们知道这些包装器使集合对于简单操作(如Collections.synchronizedMap()
)是线程安全的,但需要manual synchronization进行迭代。这也意味着所有访问都需要通过同步包装才能保证安全。
如果这不是JSF错误,我们可以假设还有另一个可以访问该映射的线程,并且它表现不佳。但是,如果这是一个多线程问题,那么错误应该如此一致地显示出来有点奇怪。
我需要更多访问系统才能提供更多信息(这不是要求更多访问权限)。
编辑:
如果不清楚,则问题正在发生,因为get()/put()
正在进入会话并且已经存在该键的值。当他们被比较时,如果它们相等,则会修改会话中的地图并抛出LinkedHashMap
。
答案 1 :(得分:1)
Servlet被重用,因此需要线程安全。
我的猜测是你的代码使用LinkedHashMap
,它是servlet的静态字段或实例字段,在web调用期间会被修改。
您的开发环境显然没有使用并发调用进行测试,因此不会遇到并发问题。
最简单的解决方法是将地图实现更改为threadsafe ConcurrentHashMap
,或者重新组织代码以使用地图副本,或者在修改时避免并发访问。
答案 2 :(得分:-3)
这是一个很长的镜头,但请记住,您只有一个servlet类实例为所有请求提供服务。因此,如果你的servlet类有任何带迭代器的字段,这可能会发生,因为2个线程试图使用相同的迭代器。
如果不是这样:尝试获取在远程服务器上运行的整个tomcat服务器的副本。您应该能够将其作为tar文件获取,然后将其解压缩并在您的计算机上运行。此问题可能是由于不同的tomcat版本或tomcat配置。