0

HTTP 500 でエラーが発生した場合に、意味のある応答をユーザーに確実に提供したい JSF アプリがあります。 OutOfMemoryError を強制するとアプリが停止しますが、Tomcat 6.0.35 からデフォルトの 500 エラーページが表示されます。

私のアプリ設定の関連部分は次のとおりです。

web.xml:

<filter>
    <filter-name>Error</filter-name>
    <filter-class>myApp.ErrorFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Error</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

...

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/expiredIndex.jsf</location>
</error-page>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.jsf</location>
</error-page>

エラーフィルター.java:

public class ErrorFilter implements Filter {

static Logger logger = Logger.getLogger("MYAPP");

@Override
public void destroy() {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
        chain.doFilter(request, response);
    } catch (ServletException e) {
        logger.error(getDirID()+"|"+"Caught Servlet Exception");
        Throwable rootCause = e.getRootCause();
        logger.error(getDirID()+"|"+"Root cause is " + rootCause.toString());

        if (rootCause instanceof RuntimeException) { // This is true for any FacesException.
            logger.error(getDirID()+"|"+"Rethrowing exception as RuntimeException" + rootCause.toString());
            throw (RuntimeException) rootCause; // Throw wrapped RuntimeException instead of ServletException.
        } else {
            throw e;
        }
    }
}

@Override
public void init(FilterConfig arg0) throws ServletException {
}

public String getDirID() {
    DirID newDirID = new DirID();
    String dirID = newDirID.getDirID();

    return dirID;
}

}

あなたの喜びのためのカットダウンスタックトレース:

2012-09-17 17:35:51,881|ERROR|[http-8080-1]:Exception in the filter chain
javax.servlet.ServletException: Servlet execution threw an exception
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

...

Caused by: java.lang.OutOfMemoryError: Java heap space
at com.sun.facelets.util.FastWriter.overflow(FastWriter.java:50)
at com.sun.facelets.util.FastWriter.write(FastWriter.java:57)

...

 Sep 17, 2012 5:35:51 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
    at myApp.DirID.getDirID(DirID.java:27)
    at myApp.ErrorFilter.getDirID(ErrorFilter.java:50)
    at myApp.ErrorFilter.doFilter(ErrorFilter.java:31)

そしておそらく最も関連性の高いビット:

Sep 17, 2012 5:35:51 PM com.sun.faces.lifecycle.Phase doPhase
SEVERE: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@16968dd]
Sep 17, 2012 5:35:51 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
javax.faces.application.ViewExpiredException: viewId:/error.jsf - View /error.jsf could not be restored.

これについての私の見解は、コンテナーが最大メモリ制限に達すると死ぬため、スタックが残っている状態では error.jsf posh エラーページにアクセスできないということです。

私の質問は次のとおりです。

  1. 原因が突然のメモリ不足エラーであることを考えると、サーバーが error.jsf ページにリダイレクトするのに十分であるように、これから戻ってくることはできますか?
  2. 1 に対する答えが「はい」の場合、実装の最も効率的な方法は何ですか (できれば最大限の知識を得るためにコード スニップを使用します)。

ありがとう

4

2 に答える 2

1

基本的に、1 の答えは「いいえ」です。OOM エラーから回復しようとすべきではありません (詳細はこちらを参照し、コメントと回答で提供されているリンクを確認してください)。エラーは、Tomcat ログと Web アプリケーション ログ (存在する場合) に投稿されます。

OOM を取得した場合は、VisualVMのようなプロファイラーを使用して、問題の可能性がある場所を確認し、問題の解決を試みます。

追加情報:


別のこととして、エラー コードを使用してエラーを処理できます。これを web.xml に追加するだけです。

<error-page>
    <error-code>500</error-code>
    <location>/ErrorForCode500.html</location>
</error-page>
于 2012-09-17T23:05:10.413 に答える
1

OOM 例外が発生すると、アプリケーション全体の状態が疑わしいため、回復することはできません。それを処理しようとすることは一種の崇高なことですが、それが起こらないようにすることははるかに重要です.

于 2012-09-17T23:09:12.390 に答える