2016-09-08 15 views
0

私は契約者が開発したJavaアプリケーションをサポートしています。私の経験は主に.NETであり、アプリケーションコードの知識を持つ人にはアクセスできません。このアプリケーションは、Eclipse内のTomcatサーバー上で実行している場合、開発環境で正常に動作します。しかし、WARをリモートサーバ(まだ開発環境にある)に配備した後、コンカレント変更例外が発生します。私はジャンプして、すべてのアプリケーションコードを行単位でレビューする前に、何が起こる可能性があるのか​​を見たいと思います。Java ConcurrentModificationExceptionはデプロイされた環境にのみあります

私が理解していることは、通常、イテレータオブジェクトを反復処理中に変更することによって発生します。しかし、なぜEclipseで実行しているときに例外が発生しませんでしたか?これがコード内のバグを確認するためのものであれば、Eclipseが例外をトリガーしていない場合、コード内のどこにあるのかを見つけるにはどうすればよいですか?例外トレースは私にはあいまいです(下に貼り付けます)。表示される唯一のファイル参照は、ビューテンプレートとです。デプロイされたアプリケーションに依存してデバッグする必要がある場合、このバグがどこにあるのかをどのようにして知ることができますか?これは環境問題である可能性がありますか?そうであれば、それを引き起こす可能性がありますか?

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

これはあなたが所有するコードで発生しますか?つまり、内部ソースまたは外部ライブラリからのこのスタックトレースの原因は何ですか? – Makoto

+0

イテレータの外側で* iterated *オブジェクトを修正し、 'iterator'自体を変更しない場合、例外がスローされます。 1つの可能性は、別のスレッドからの変更です。反復ループにマップを変更するものがあります。複数の同時セッションがないため、ローカルビルドで例外が発生しない可能性があります。しかし、あなたがすべき最初のことはどこに*問題があるかを知ることです。スタックトレースにカスタムパッケージが見つかりません。 – Ordous

+0

@Makoto正直なところ、私はどのように伝えるべきかわかりません... – matikin9

答えて

-3

これは非常に長いですが、サーブレットクラスのインスタンスが1つしかないことに注意してください。したがって、サーブレットクラスにイテレータを持つフィールドがある場合、2つのスレッドが同じイテレータを使用しようとするため、これが発生する可能性があります。

そうでない場合は、リモートサーバー上で実行されているTomcatサーバー全体のコピーを取得してください。あなたはtarファイルとして取得し、それを解凍してコンピュータ上で実行できるはずです。この問題は、さまざまなTomcatのバージョンまたはTomcatの設定に起因する可能性があります。

1

スタックトレースは内部API(Tomcat、JSF、JDK)のみを示しているので、結論を出すのは難しいです。われわれが知っているように、ConcurrentModificationExceptionは、fail-fastコレクションを繰り返し処理しているときに発生し、繰り返し中に変更されます。これは別のスレッドから発生する可能性がありますが、同じスレッドから同じように簡単です。その仕組みがわからない場合は、SOに例がたくさんあります。

変更が同じスレッドで発生していると仮定すると、スタックトレースには犯人が表示されます。この場合、それは約com.sun.faces.context.SessionMap.put(SessionMap.java:138)のどこかにあるでしょう。

コード(doSet = ! result.equals(value);)およびスタックトレースに基づいて、それは我々がスタックトレースから見ることができる、valueLinkedHashMapの平等をチェックしていますもLinkedHashMapです。

しかし、resultCollections.synchronizedMap()で囲まれています。これは、ラッパーが単純な操作(たとえば、get()/put())に対してスレッドセーフなコレクションを作成しますが、反復にはmanual synchronizationが必要であることがわかっているため、重要です。また、すべてのアクセスが安全な状態に保たれるように同期ラッパーを通過する必要があることも意味します。

これはJSFのバグではない場合、そのマップにアクセスできる別のスレッドがあり、うまく動作しないと考えられます。しかし、これがマルチスレッドの問題である場合は、エラーが一貫して表示されることはやや奇妙です。

これ以上アクセスできるようにするためには、より多くの洞察力を与えるためにシステムにアクセスする必要があります。

EDIT: 明らかでない場合は、LinkedHashMapがセッションに挿入されていて、そのキーの値が既に存在するため、問題が発生しています。それらが等しいかどうか比較されるとき、セッションに入れられる地図は変更され、ConcurrentModificationExceptionがスローされます。

+0

それは私にアイデアを与えます - 私はこれが起こっているところで私に多くの情報を与えるためにキャッチする例外を更新することができます。テストする前にすべての変更を再デプロイする必要があるので、ちょっと迷惑なことです。 – matikin9

+0

私の編集を見ましたか? – Kayaman

1

サーブレットは再利用されるため、スレッドセーフである必要があります。

私の推測では、コードはLinkedHashMapを使用しています。これは、サーブレットの静的フィールドまたはインスタンスフィールドのいずれかであり、Web呼び出し中に変更されます。

あなたの開発環境は同時呼び出しではテストされていないため、並行性に問題はありません。

最も簡単な修正は、マップの実装をスレッドセーフConcurrentHashMapに変更するか、マップのコピーを使用するようにコードを再編成するか、そうでなければ変更中の同時アクセスを避けることです。

+0

私はコード内にいくつかのHashMapsを見たことがありますが、これは一歩一歩踏み外すことです。私はちょうどそれをぶち込まなければならないように見えます。 : '(また、私が唯一のユーザであるときに遠隔のTomcatが同時呼び出しをどのようにしているのか分かりません。 – matikin9

+0

stacktraceの大きなヒントは 'java.util.AbstractMap.equals'です。 '.equals()'を使ってマップを比較するか、SetやMapキーでマップを追加/検索する場合に暗黙的にこれを呼び出します。また、サーバーをデバッグモードにして、IDEを接続してブレークポイントを'LinkedHashMap $ LinkHashIterator.nextEntry()'ここで例外をスローし、デバッグ情報を調べて手がかりを探します。 – Bohemian

関連する問題