1

調査しているいくつかのオープンソースコードで、次の状況が発生しています。これは、次のことを行う同期ブロックを使用しています。

  1. プライベートブールインスタンス変数hasListenerをtrueに設定します
  2. インスタンス変数内に例外を格納する大きなtryブロックを使用してwait()を実行するメソッドを呼び出します
  3. hasListenerをfalseに設定します
  4. 以前に保存された例外をスローします

同じクラスに、まったく同じことを行う別の同様のメソッドがあります。

理論的には、これにより、入力時にhasListenerがfalseになるようにする必要があります。しかし、どういうわけか、例外が下部にスローされています(//?とマークされたコメントを参照)。これは、メソッドに入り、hasListenerがtrueであるためです。hasListenerが設定されている場所が他になく、デフォルト値がfalseであることを確認しました。waitFirstMessage()の下部で例外をスローすると、変数がfalseに戻されなくなるという考えられる状況はありますか?他に考えられる状況はありますか?

ログからは、正当な例外が発生しているように見え(「操作を完了するまでの時間が超過しました」)、その時点から例外(//?)がかなり頻繁にスローされます。

protected void waitFirstMessage (int msgId) throws LDAPException {
    synchronized (this) {
        if (!hasListener) {
            hasListener = true;
            while ((request != null) && (request.id == msgId) &&
                (m_exception == null) && (response == null)) {
                waitForMessage();
            }        
            hasListener = false;
            // Network exception occurred ?
            if (m_exception != null) {
                LDAPException ex = m_exception;
                m_exception = null;
                throw ex;
            }
        } else {
            //?
            throw new LDAPException();
        }
    }
}

 private void waitForMessage () throws LDAPException {
    try {
        if (request.timeToComplete > 0) {
            long timeToWait = request.timeToComplete -
                System.currentTimeMillis();
            if (timeToWait > 0) {
                wait(timeToWait);
                if (notified) {
                    notified = false;
                } else if (request.timeToComplete < System.currentTimeMillis()) {
                    // Spurious wakeup before timeout.
                    return;
                } else {
                    request = null;
                    m_exception = new LDAPException(
                        "Time to complete operation exceeded",
                        LDAPException.LDAP_TIMEOUT);
                }
            } else {
                request = null;
                m_exception = new LDAPException(
                    "Time to complete operation exceeded",
                    LDAPException.LDAP_TIMEOUT);
            }
        } else {
            wait();
            notified = false;
        }
    } catch (InterruptedException e) {
        m_exception = new LDAPInterruptedException("Interrupted LDAP operation");
    } catch (Exception e) {
      m_exception = new LDAPException("Unexpected exception while waiting for response",
          LDAPException.OTHER, e.getMessage());
    }
}

編集

わかりました、私の質問は間違っていたことがわかりました。ログの取得元である本番環境で現在実行されているバージョンは、私が見ていたコードよりもわずかに早く、誰かがこの問題に明確に対処しています。以前のバージョンでは、waitForMessage()メソッド例外をスローしていました。これらは中断waitFirstMessage(int msgId)hasListenerていて、falseに設定されることはありませんでした。宇宙は再び理にかなっています。

返信ありがとうございます。次に、この修正を本番環境に移行する必要があります。

4

2 に答える 2

0

hasListenerwaitForMessageスローする場合はtrueに設定されたままになります。すべての例外をキャッチするのでwaitForMessage、これは、例外ではない何かがスローされた場合(他の何かThrowable)、またはの開始中に例外がスローされた場合にのみ当てはまる可能性がありm_exceptionます。

于 2012-11-15T22:08:49.553 に答える
0

waitForMessage例外をスローして突然完了すると、hasListener = false到達しません。このコードが確実にhasListener = false実行されることを意図していた場合は、それをfinallyブロックに配置する必要がありました。

于 2012-11-15T22:05:47.547 に答える