質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JVM

JVM(Java Virtual Machine)があれば、一連のコンピューターソフトウェアプログラムとデータストラクチャが、仮想マシンモデルを使って他のコンピュータプログラムやスクリプトを拡張できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Struts 2

Apache Struts 2は、Apache Strutsプロジェクトにて開発されているオープンソースのJavaベースのWebアプリケーションフレームワークです。Sturts1に比べ、設定ファイルの削減、依存性の注入、POJO等の改善がなされています。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Apache Tomcat

Apache TomcatはApache Software Foundation (ASF)で開発されたオープンソースのWebコンテナです。

Q&A

1回答

1556閲覧

GC中の0byteのレスポンス

chinsukooo

総合スコア13

JVM

JVM(Java Virtual Machine)があれば、一連のコンピューターソフトウェアプログラムとデータストラクチャが、仮想マシンモデルを使って他のコンピュータプログラムやスクリプトを拡張できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Struts 2

Apache Struts 2は、Apache Strutsプロジェクトにて開発されているオープンソースのJavaベースのWebアプリケーションフレームワークです。Sturts1に比べ、設定ファイルの削減、依存性の注入、POJO等の改善がなされています。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Apache Tomcat

Apache TomcatはApache Software Foundation (ASF)で開発されたオープンソースのWebコンテナです。

0グッド

2クリップ

投稿2019/02/08 06:46

編集2019/02/14 00:51

GCのタイミングでHTTPステータス200、0byteのレスポンスが返却されます。

** わかっていること **

  • tomcatのEden領域の使用率が100%なって、GCが発生するタイミングにアクセスすると発生する。
  • デプロイされたモジュール内の静的なコンテンツ(例えば404.htmlなど)にアクセスしても発生しない
  • ActionクラスやControllerを実行するようなアクセスの場合に発生する。
  • Struts2で作ったものも、Springで作ったものを発生する(フレームワークのせいではなさそう)
  • tomcatのcatalina.outに、0byteのレスポンスが発生した時に以下のエラーが出る。

java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできません

GCのタイミングでアクセスするとしょうがないものなのでしょうか?

だれが0byteのレスポンスを返しているのかもわかっていません。

どこかで(勝手に)0byteのレスポンスを返してしまっているから、「レスポンスをコミットした後でフォワードできません」のエラーが出ている気がしています。
なにか確認すべきことや似た事象があれば教えてください。
よろしくお願いします。

java 1.6
tomcat 6.0.33

追記
tcpdumpを取得してみました。
HTTPステータスは200で、レスポンスBODYが存在しません。
Next Sequene number:136 で
841行目で正常に処理できたことが確認できると思います。

tcpdump結果キャプチャ

追記2
コールスタックを貼ります。

callStack

1java.lang.Thread#run 2org.apache.tomcat.util.net.JIoEndpoint$Worker#run 3org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler#process 4org.apache.coyote.http11.Http11Processor#process 5org.apache.catalina.connector.CoyoteAdapter#service 6org.apache.catalina.core.StandardEngineValve#invoke 7org.apache.catalina.valves.AccessLogValve#invoke 8org.apache.catalina.valves.ErrorReportValve#invoke 9org.apache.catalina.core.StandardHostValve#invoke 10org.apache.catalina.core.StandardContextValve#invoke 11org.apache.catalina.core.StandardWrapperValve#invoke 12org.apache.catalina.core.ApplicationFilterChain#doFilter 13org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 14org.seasar.extension.filter.EncodingFilter#doFilter 15org.apache.catalina.core.ApplicationFilterChain#doFilter 16org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 17XXXXXXXXXXXXXXXXXXXXXX.filter.XXXXXXXXXX.XXXXXXX#doFilter // フィルタA 18org.apache.catalina.core.ApplicationFilterChain#doFilter 19org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 20XXXXXXXXXXXXXXXXXXXXXX.filter.XXXXXXXXXX.XXXXXXX#doFilter // フィルタB 21org.apache.catalina.core.ApplicationFilterChain#doFilter 22org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 23org.seasar.framework.container.filter.S2ContainerFilter#doFilter 24org.apache.catalina.core.ApplicationFilterChain$#doFilter 25org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 26org.seasar.framework.container.hotdeploy.HotdeployFilter#doFilter 27org.apache.catalina.core.ApplicationFilterChain#doFilter 28org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 29org.seasar.struts.filter.RoutingFilter#doFilter 30org.seasar.struts.filter.RoutingFilter#forward 31org.apache.catalina.core.ApplicationDispatcher#forward 32org.apache.catalina.core.ApplicationDispatcher#doForward // 0bytの時はここでIllegalStateExceptionが発生 33org.apache.catalina.core.ApplicationDispatcher#processRequest 34org.apache.catalina.core.ApplicationDispatcher#invoke 35org.apache.catalina.core.ApplicationFilterChain#doFilter 36org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 37org.seasar.framework.container.filter.S2ContainerFilter#doFilter 38org.apache.catalina.core.ApplicationFilterChain#doFilter 39org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 40org.seasar.framework.container.hotdeploy.HotdeployFilter#doFilter 41org.apache.catalina.core.ApplicationFilterChain#doFilter 42org.apache.catalina.core.ApplicationFilterChain#internalDoFilter 43javax.servlet.http.HttpServlet#service 44javax.servlet.http.HttpServlet#service 45org.apache.struts.action.ActionServlet#doGet 46org.apache.struts.action.ActionServlet#process 47org.apache.struts.util.ModuleUtils#selectModule 48org.apache.struts.util.ModuleUtils#getModuleName 49org.apache.struts.util.ModuleUtils#getModuleName

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wwbQzhMkhhgEmhU

2019/02/08 07:28

0バイトのレスポンスというのは誰が判断しているのでしょうか? パケットはキャプチャしましたか?
chinsukooo

2019/02/08 07:39

アプリを乗せてるサーバーで、localhostでcurlして確認しています。ブラウザからアクセスしてapacheのアクセスログでも確認しています。 httpステータス200 レスポンスバイト数 -(0バイト)
wwbQzhMkhhgEmhU

2019/02/08 07:52

tomcat-apache-ブラウザという通信で、apacheでhttpステータス200 レスポンスバイト数 -(0バイト) しか分かっていないということですね。簡単に再現できて、apacheを介さずにtomcatにアクセスできるのであれば、ブラウザを動かしているクライアントでキャプチャした方がいいと思います。できない場合は、状況次第なのでよく分かりません。自分なら調べますが。
chinsukooo

2019/02/08 07:58

ブラウザで直接tomcatにはアクセスできませんが、tomcatがいるサーバーでcurlしてレスポンスが空っぽなことは確認しています。wgetで0バイトのファイルができることも確認済みです。
wwbQzhMkhhgEmhU

2019/02/08 08:05

httpの通信はリクエストもレスポンスもヘッダとコンテントがあります。 それらがどう来ているのかを確認すべきです。 通信の発生しない、しかもキャプチャも出来ていない内容ではよく分かりません。 tcpdumpくらいできるはずですし、自分で書いても確実に残せますよね。 なお、curlはヘッダを残せるはずですよね?そこではどうなっていますか? content-lengthはついていますか?
chinsukooo

2019/02/08 08:55

ついていないです。ボディがないです。 $ curl -i http://localhost:XXXX/XXXX/XXXX/ HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Transfer-Encoding: chunked Date: Fri, 08 Feb 2019 08:33:21 GMT Connection: close
wwbQzhMkhhgEmhU

2019/02/08 09:00

チャンク転送の場合で、結合後の中身0バイトならボディは0になりますよね? だとすると、レスポンスを送る際にサーバ側が切ったか、クライアント側が切ったかしたんじゃないでしょうか? tomcat側の出方から推測すると、クライアント側(apache)が切っている可能性がありますね。パケットを見れば分かりますが、どちらが切ったかはこの情報からだけでは分かりません。
chinsukooo

2019/02/08 09:35

apacheとtomcatは別のサーバーにいます。上記curlはtomcatがいるサーバーで叩いているので、apacheが切っている、というのはないと思っています。
wwbQzhMkhhgEmhU

2019/02/08 09:44

連携は認識していますよ。本来ならapacheで再現すべきところをcurlを使ってるから言い換えてるだけです。
wwbQzhMkhhgEmhU

2019/02/08 09:49

伝わっているのか分からないのでちゃんと言っておくと、「tomcat側の出方」は「java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできません」に言及したものです。
chinsukooo

2019/02/08 10:01

ありがとうございます。環境的な問題で、キャプチャはすぐには取れないので、取れたら追記させていただきます。
退会済みユーザー

退会済みユーザー

2019/02/08 10:10

ReqestDiaptcher.forward()が呼ばれてJSP/Servletが出力処理する前に、OutputStreamが閉じられたか/コミットされた。応答は200OK。その後、JSP/ServletでコンテンツをOutputStreamにwrite()したときにIllegalStateExceptionが発生したというのが、予想シナリオです。メモリー不足で例外が発生し、その例外処理のところでOutputStreamを閉じているのかな、という推測をしています。開発環境でedenを食い尽す処理(巨大サイズの配列をつくるなど)をforwardの前に入れて、OutputStreamがなぜ閉じられるのかを観察できないでしょうか。 StackOverFlowの情報です。 https://stackoverflow.com/questions/14959986/tomcat-error-500-on-servlet-cannot-forward-after-response-has-been
chinsukooo

2019/02/08 10:14

ありがとうございます。これはすぐに試せそうです。実験結果はまた追記します。
wwbQzhMkhhgEmhU

2019/02/08 13:57

今日のところは追加がないようなので、とりあえず書いておきます。 チャンク転送時にボディがないと言っていたのは、何を根拠にしていますか?チャンクを結合した後のサイズが0ということであれば、必ずしも切断は必要ありません。私はパケットキャプチャなり素の通信から始めるので、つい何も考えずに切断されたと思ってしまいましたが、パケットキャプチャもしないでこういう現象を追い始める人なら、ソフトの判定を根拠にボディがないと言っている気がしてきました。 チャンク転送というのは、長さが分からないレスポンスを先にヘッダだけ返してからチャンクという単位でダラダラ、コンテントを書くようなときに使用するエンコーディングです。 また、一応念の為、実際にcurlで試した際に、tomcat側では同じ現象が起きていることを確認してください。同じ現象でないと意味がないので。 現状は高負荷(?)時ということもあり、外側から固めてもらっていた次第ですが、amdahlslawさんは、コードから追っていくようですね。その場合はバージョンをもっと細かく聞いてログをもっとしっかり見た方がいいかと思いますよ。 アロケーションに失敗するような所謂エラー(ランタイム例外ではなく)が起きてしまったら、多分アプリかVMごと落ちると思うので、多分何らかの別の例外が起き、最初のチャンクを待たずに0で終わったか、0も送らずに切断したかのされたかのいずれかだと思います。現象が正確に分かったら、ログをよく読み、Tomcatのバージョンを特定してソースから追っかけてけば、ある程度何が起きたかを予想できるのではないかと思っています。情報次第ですけどね。
wwbQzhMkhhgEmhU

2019/02/12 04:24

チャンク部分の出力はあるようですね。 End of chunked encodingのところは多分0\r\n ですよね? 少なくともその先の\r\nはチャンク転送の一部です。 つまり、ソフトの判定を根拠にボディがないと言っているだけで、チャンクを結合した後のサイズが0というだけですね。その後リセットされたのでもなく、クライアントから普通に切断が来て、サーバー側も切断しています。 正しくはどうなるはずだったのでしょうか? tomcatのログ上はどうなっていますか?
chinsukooo

2019/02/12 04:38

はい。おっしゃるとおり、「\r\n」です。 正しくは、この場合はHTTPステータス302でリダイレクトされるのが正しいです。 tomcat上は「java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできません」が出力されています。
wwbQzhMkhhgEmhU

2019/02/12 04:56

ん?ログの設定はどうなっていますか? それ以外何も出してないのです?
wwbQzhMkhhgEmhU

2019/02/12 04:57

あと、0\r\nではなかったですか?
chinsukooo

2019/02/12 05:13

「\r\n」でした。 -HTTP chunked response -End of chunked encoding Chunk size: 0 octets \r\n
chinsukooo

2019/02/12 05:16

すいません、一部マスクしていますが、以下ログになります。 XXXX/XX/XX XX:XX:XX org.apache.catalina.core.StandardWrapperValve invoke 致命的: サーブレット default のServlet.service()が例外を投げました java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできません at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312) at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302) at org.seasar.struts.filter.RoutingFilter.forward(RoutingFilter.java:219) at org.seasar.struts.filter.RoutingFilter.doFilter(RoutingFilter.java:90) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.seasar.framework.container.hotdeploy.HotdeployFilter.doFilter(HotdeployFilter.java:71) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.seasar.framework.container.filter.S2ContainerFilter.doFilter(S2ContainerFilter.java:79) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at XXXXXXXXXXXXXXXXXXXXXX.filter.XXXXXXXXXX.XXXXXXX(XXXXXXXXXX.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at XXXXXXXXXXXXXXXXXXXXXX.filter.XXXXXXXXXX.XXXXXX(XXXXXXXXXXX.java:50) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.seasar.extension.filter.EncodingFilter.doFilter(EncodingFilter.java:69) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 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:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.ha.tcp.ReplicationValve.invoke(ReplicationValve.java:347) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:610) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) at java.lang.Thread.run(Thread.java:662)
wwbQzhMkhhgEmhU

2019/02/12 05:21

フォワードする直前に送ってるものが200 OKなのではないかと思ってて、バッファが溢れたとかを疑っています。直前のリスエスト・レスポンスは正しく授受できていますか?
chinsukooo

2019/02/12 05:36

GCが起こる直前の同じURLに対するリクエストは、きちんとステータス302でリダイレクトで返却されています。 バッファが溢れた、とは具体的にどういったイメージでしょうか?
wwbQzhMkhhgEmhU

2019/02/12 05:50

正確な理解でなくてすみませんが、サーブレットはHTTPのレスポンスを自分で書いていて、それを送信しているのですが、これは一度バッファリングされてから、コミットされたタイミングで出ていくもののようなのです。なので、例えば、GCで固まっている間に溜まった処理により、コミットのタイミングまでにバッファが溢れたとかなのかな。。。と。
wwbQzhMkhhgEmhU

2019/02/12 05:59

ん?GCが起こる直前? GCはどうやって起こしてるんですか?
chinsukooo

2019/02/12 06:15

画面にアクセスするたびにEden領域の使用率が上がっていき、下がることはないです。 Eden領域の使用率が100%になるとGCが発生して使用率がまた1%以下になります。 実際には可能中のシステムなので、継続していろんなページへのアクセスがあるので、GCを起こしているというよりは勝手に発生しています。そのタイミングを狙ってtcpdumpを取ったりしています。
wwbQzhMkhhgEmhU

2019/02/12 06:54

では、この現象は、どのリクエストに対してでも起こるのでしょうか? それとも特定のリクエストだけですか?
wwbQzhMkhhgEmhU

2019/02/12 07:02

あと、直前がリダイレクトで終わるというのもおかしな話です。リダイレクト先は別のサーバなのですか?
chinsukooo

2019/02/12 07:05

質問内にも記載していますが 「デプロイされたモジュール内の静的なコンテンツ(例えば404.htmlなど)にアクセスしても発生しない」です。 StrutsであればActionクラス、SpringであればControllerクラスを実行するようなものであれば、どんなリクエストでも発生しています。 ただ、0byteのレスポンスが発生した時は、Actionクラスの先頭に仕込んだログも出力されません。フレームワークのDEBUGログとかも出してみましたが、0byteレスポンスの時は出力されません。 0byteのレスポンスの時はアプリケーションの処理まで到達しているようには見えません。
chinsukooo

2019/02/12 07:15

リダイレクトに関して、すいません。 「直前」というのは、GCが起る直前の同じURLへのアクセス、と言う意味です。 GC前:/hoge/ にアクセス ⇒ HTTP/1.1 302 Found(正しい) GC中:/hoge/ にアクセス ⇒ HTTP/1.1 200 OK (0byte) GC後:/hoge/ にアクセス ⇒ HTTP/1.1 302 Found(正しい) リダイレクト先は同じサーバーです。 ちなみにこの例がたまたまリダイレクトになっているだけで 200でなにかhtmlのページを返すURLでも、テキストを返すURLでも、なんでもGC中は0byteのこの現象が起ります。
wwbQzhMkhhgEmhU

2019/02/12 07:19

いや、302でリダイレクトしたなら、その先を取ってくるはずなのですが、今はcurlでやられていて、リダイレクト先を追わない設定にでもしているのですか?
chinsukooo

2019/02/12 07:29

gcしてない時の302レスポンスのあとは、リダイレクトして目的のページまでたどり着けています。
chinsukooo

2019/02/12 07:32

すいません、同じURLでgc実施前後を出した方がわかりやすいと思い、上記のような回答をしていました。 実際にはgcの前には302ではなく200のcontents-type:htmlのものを返却するアクセスがあり、それはちゃんと中身を返せていました。
wwbQzhMkhhgEmhU

2019/02/12 07:42

正常にコンテントを返した200の後に、中身のないチャンク転送の200が続くということでいいですか? あと正常にコンテントを返した200のときは、チャンク転送だったか分かりますか? リクエストとの対応関係も取れていますか? Ethereal(今は名前違うんでしたっけ?)でダンプしたものを見ている/実際にキャプチャしているなら、TCPのストリームを追う画面があったはずです。それで見ると楽だと思います。
chinsukooo

2019/02/12 08:12

ありがとうございます。すいません、回答はまた明日になってしまいます。 ダンプはwireSharkで見ています。 またよろしくお願いします。
wwbQzhMkhhgEmhU

2019/02/12 08:16

了解です。あと分かるなら Tomcatの正確なバージョン seasarはよく知らないので、これもバージョン もお願いします。 他には可能であればTomcatのバッファサイズ確か変更できたと思ったので、広げて試したりもしてみてほしいです。それでは。
chinsukooo

2019/02/13 01:55

こんにちは。遅くなってしまいましたが確認しました。 GCが発生したタイミングで、1秒ほど中身のないチャンク転送の200が続きます。 正常に返す時もチャンク転送です。(HTTP chunked response と出ているのでそう判断しています。) tomcatは6.0.33です。 ヒープ領域やバッファサイズも増やしたりしましたが、GCが発生する間隔が広がっただけで、GCのタイミングで0byteレスポンスが発生するのは変わりませんでした。
wwbQzhMkhhgEmhU

2019/02/13 02:27

了解です。amdahlslawさんの情報までは確認できて、現象も不一致がない状態ですね。 200の部分で起きている現象を確認しないとですね。ヒープサイズは変えてもしょうがないかと思いますが、バッファが効かなかったのはちょっと困りましたね。変更したパラメータと前後の値を教えてください。 長くなったので、以降はamdahlslawさんの回答の方に移りますね。
guest

回答1

0

情報提供

スタックトレースから読めるのは、次のようなエラーの発生状況です。

HTTPリクエスト受付 -> サーブレットフィルター処理 -> ... -> defaultサーブレットのservice処理へ転送

defaultサーブレットはStrutsのフロントコンポーネント(すべてのリクエストを受け付けるサーブレット)ではないかと思います。

転送は、ApplicationDispatcher(RequestDispatcher)の doForward で実行。

stack

1org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312)

例外メッセージは「レスポンスをコミットした後でフォワードできません」なので以下のプロパティが使われたと想定。

properties

1applicationDispatcher.forward.ise=レスポンスをコミットした後でフォワードできません

ApplicationDispatcherのソースコードを見ます。(正確なバージョンがわからないので行番号(312)が一致したもの)

Java

1 private void doForward(ServletRequest request, ServletResponse response) 2 throws ServletException, IOException 3 { 4 5 // Reset any output that has been buffered, but keep headers/cookies 6 if (response.isCommitted()) { // <------- (1) isCommited 7 throw new IllegalStateException 8 (sm.getString("applicationDispatcher.forward.ise")); // <------- (2) property 9 } 10 try { 11 response.resetBuffer(); 12 } catch (IllegalStateException e) { 13 throw e; 14 }

最初の IllegalStateException を投げているところ、(1)の response.isCommitted() に該当するようです。つまり、レスポンスはすでにコミットされた。では、誰がコミットしたのか?それは、リクエスト処理を実行しているスレッドのはず、手前にあるサーブレットフィルターのどれかではないでしょうか。(困るんだけど...)

ついでにいうと、ServletResponseは本物でない可能性があります。Servletの仕様では ServletResponseWrapper を許すので、ラッパーの内部で、実際の出力内容をメモリにキャッシュすることもできます。GCの状況から、手前のサーブレットフィルターのどれかが、キャッシュ用のメモリが確保できないのでギブアップした、などが想像できます。

以上、情報提供だけです。

参考
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwiuyOXOy7XgAhUP8LwKHSzlB7kQFjAAegQICRAB&url=https%3A%2F%2Fsvn.apache.org%2Frepos%2Fasf%2Ftomcat%2Ftrunk%2Fjava%2Forg%2Fapache%2Fcatalina%2Fcore%2FApplicationDispatcher.java&usg=AOvVaw04faUFOh_JgqIvFQpDqTZx

https://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/catalina/core/LocalStrings_ja.properties

フレームワークではない
Tomcatのコンポーネントを疑うべきでしょうか。

投稿2019/02/12 11:03

編集2019/02/12 12:13
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chinsukooo

2019/02/12 12:49

情報提供ありがとうございます。 今のところ、どんなフレームワークのものでも発生しています。 tomcatのコンポーネントは調べてまた追記します。 詳細な情報ありがとうございます。
wwbQzhMkhhgEmhU

2019/02/13 02:35

あ、あとseasarのバージョンも教えてください。strutsが独自なんだか、よく知らないので。 今追っている現象では、strutsが呼ばれているのです。すみませんがお願いします。
wwbQzhMkhhgEmhU

2019/02/13 02:40

それからTCPストリームを追った結果になりますが、全てリクエストされてるURLは同じでしたか? 特に200を返したときのリクエストURLです。
chinsukooo

2019/02/13 02:42

バッファサイズは指定なし(2048byte)から10485760byteまであげてみましたがなにも変わりませんでした。 seasarは2.4.46です。
wwbQzhMkhhgEmhU

2019/02/13 02:44

パラメータの名称もお願いします。
chinsukooo

2019/02/13 04:11

Connectorタグ内のbufferSizeで指定しています。「bufferSize="10485760"」
wwbQzhMkhhgEmhU

2019/02/13 04:18

それは入力用という時点で違うので、socket.appWriteBufSizeでお願いします。
wwbQzhMkhhgEmhU

2019/02/13 04:19

あとリクエストされてるURLがないと追えないですよ。転送するパスとは違うと思うので。
chinsukooo

2019/02/13 04:24

socket.appWriteBufSizeを指定して実験してみます。ちょっと時間かかると思いますがここでご報告します。ありがとうございます!
wwbQzhMkhhgEmhU

2019/02/13 04:24

なお万一全てが同じURLだった場合も考えて、もし例外発生があり、異なる分岐をしたらどうなるかを少し見てみましたが、 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) でUnavailableExceptionで501/503を返す経路くらいしか見つかりませんでした。 これらがさらに全て200に化ける経路というのも考えにくい気がします。 ただし、xxxxxで隠されているフィルタ2つについては不明です。
wwbQzhMkhhgEmhU

2019/02/13 04:24

いや先にURLを。。。ずっと昨日から聞いてるんですけども。。。
chinsukooo

2019/02/13 05:14

いつも同じURLで0byteが返ってくるのか?という意味ですか? 同一サーバー内の違うモジュールでも0byteが返却されます。 同一モジュール内でも、色々なパスで0byteが返却されています。
wwbQzhMkhhgEmhU

2019/02/13 05:34

実際にGC発生中にアクセスしているリクエストURLが全て同じで、例外発生時のURLと同じなのか?という意味でした。 では、例外発生直前のリクエストURLはどんなものですか? 本来だとどういうものだったのでしょうか? チャンク転送になるようなものでしたか? サイズとか転送方法とか、JSPのようなものなのか、画像や動画なのか、全く別モノなのか? 主に現状の想定と合致しているのか異なっているのか、と、どの辺の実装を見るべきかなどを考えるためです。
chinsukooo

2019/02/13 05:53

jspを返すものもあれば、画像を返すものもあります。byte数も様々です。 追加の情報になるのかどうかわからないですが、マスクしたフィルタについてもお伝えします。 2つありましてフィルタA⇒フィルタB の順番で実行されます。 ■フィルタA logger.info("ログ1"); try { chain.doFilter(request, response); // 昨日貼ったスタックトレースの XXXXXXXXXX.java:50 の行 } finally { logger.info("ログ3"); } ■フィルタB logger.info("ログ2"); chain.doFilter(request, response); // 昨日貼ったスタックトレースの XXXXXXXXXX.java:53 の行 上記のようなになっています。 0byteのレスポンスの時も、"ログ3"まで出力されることが確認できました。 このフィルタのあとにseasar2の「routingfilter」とかもあるので ログ出してもう少し見てみます。
wwbQzhMkhhgEmhU

2019/02/13 06:05

こないだはログが全く出なかったと言ってたと思いますが。。。 ログ3が出たのは分かりましたが、ログ1やログ2はどうだったんでしょう? そもそもINFOレベルで出るなら他の情報もかなり出そうな気がするんですけども。。。 そんなに細かく設定してるのでしょうか?
chinsukooo

2019/02/13 06:29

ログが全く出ない時と出る時があるような気がします。。。すいません。もう少し整理してみます。 ログ1もログ2も出ています。
chinsukooo

2019/02/13 06:50

ログに関して追記です。 0byteでない時はログ出力内容が フィルタA.ログ1 フィルタB.ログ2 org.apache.struts.util.ModuleUtils.java(167) Get module name for path XXXXXX : : フィルタA.ログ3 このように出力されていますが、0byteの時は フィルタA.ログ1 フィルタB.ログ2 フィルタA.ログ3 のように出力されていて、ModuleUtilsのログが出ていない(そこまで到達してない)ことがわかりました。
wwbQzhMkhhgEmhU

2019/02/13 07:06

ん?それseasarの方にはないような。。。
wwbQzhMkhhgEmhU

2019/02/13 07:13

なんかちゃんと構成聞いた方がいいような気がします。 どういう構成になってますか? tomcat(A)+seasar(sastruts)とtomcat(B)+spring(struts2)なのかなぁと思ってたんですが、違います?
chinsukooo

2019/02/13 09:26

すいません、一回springの方は忘れてください。ログが出ていなかった、という前提条件とか色々怪しい気がしてきたので、、、あとで編集しておきます。 とりあえずseasarの方だけ考えます。 tomcat(A) + seasar2 です。 本当は、おっしゃる通り別サーバーですが tomcat(B) + springもいますが、こっちは一旦置いておきます。
wwbQzhMkhhgEmhU

2019/02/13 09:30

springの方は忘れるとして、seasar2の方だけ考えるとすると、 org.apache.struts.util.ModuleUtils.java(167) Get module name for path XXXXXX は0byteだろうが、Nバイトだろうが、出ていなかった、と考えていいのでしょうか?
chinsukooo

2019/02/13 09:49

いいえ。0バイトの時は出なくて、正常の時は出力されます。
wwbQzhMkhhgEmhU

2019/02/13 10:01

あ、すみません。 libの中にバイナリですがstruts-1.2.9.jarが入れられてましたね。 この中にさっきのクラスが入ってました。 ブランチではなくてそのまま使っちゃってるんですね。失礼しました。
chinsukooo

2019/02/13 10:03 編集

回答かぶってしまいました。みつかってよかったです。
wwbQzhMkhhgEmhU

2019/02/13 10:55

ちょっとバージョン合わせて動く環境がないので、ソースから追ってるのもあり、もしデバッガで止められるのであれば、サーブレット(JSPでもなんでも)正常動作時のコールスタックだけでももらえると嬉しいです。
chinsukooo

2019/02/13 11:16

ありがとうございます。承知しました。明日になってしまうのですが、貼り付けます。よろしくお願いします。
wwbQzhMkhhgEmhU

2019/02/14 03:28

あ、質問の方に貼ってあったんですね。ありがとうございます。 で、早速?って感じになったのですが、つまり、中身なしの200の数だけ、Exceptionが発生、記録されている、ということですか?私は、中身なしの200が複数回記録されて、その後、Exceptionが一回だけ発生だと思っていたのですが。
chinsukooo

2019/02/14 04:08

こちらだとMarkdown使えなそうだったので、、、すいません。 Exeptionは0byteレスポンスのたびに発生しています。 3回0byteのレスポンスがあれば、3回Exeptionが発生しています。
wwbQzhMkhhgEmhU

2019/02/14 06:23

flushが怪しいと踏んでいたんですが、ちょっとよく分からなくなってきました。 Exceptionは昨日の→ログ1→ログ2→ログ3→のどこに挟まっていますか?
chinsukooo

2019/02/14 06:53

ログ2とログ3の間です。 全部貼るとすごいことになってしまいますが 大体の流れでいうと、 フィルタA:ログ1⇒フィルタB:ログ2⇒Exception発生箇所⇒Actionクラスとか・・・⇒フィルタB⇒フィルタA:ログ3 という流れです。
wwbQzhMkhhgEmhU

2019/02/14 07:15

なるほど。。。それは大変な。。。 最初にExceptionが発生したときのリクエストとその直前のリクエスト辺りが気になりますね ただ出せる情報ではない/出す作業自体が大変だと思うので、こちらでも引き続き暇なときに独自調査していくつもりですが、こちらからの成果は諦めた方がいいと思います 頑張ってください
chinsukooo

2019/02/14 07:19

自分では思い浮かばないたくさんの調査切り口を提供してくださり、感謝します。 だれがどこで0byte返却しているのか、引き続き調査します。とりあえずはフレームワーク周り、、 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問