AEM 6.x アプリケーションに JCR セッションリークがあるかどうかを確認し、そのソースを追跡します。

環境

AEM 6.x

手順

I. セッションリークがあるかどうかを確認する

  1. http://host:port/system/console/jmx に移動し、管理者としてログインします。
  2. ブラウザーの検索機能を使用して、ページ上の SessionStatistics オブジェクトの出現箇所をすべて検索します。
  3. 出現箇所が 500 を超える場合は、セッションリークが発生しています。

II.セッションリークの原因となっているコードを特定する

セッションリークが見つかった場合は、次の手順に従って原因を特定します。

  1. ページを下へスクロールして SessionStatistics オブジェクトを見つけます。
  2. 新しいブラウザータブで SessionStatistics オブジェクトをいくつか開きます。そのためには、タイムスタンプが新しいか ID 番号が大きいオブジェクトを、Ctrl キーを押しながらクリックします。例えば、12105:org.apache.jackrabbit.oak "SessionStatistics" "admin@session-12105@Aug 10, 2016 7:03:25 PM" {id=287} の ID 番号は 12105 です。ID 番号が大きいほど、最後に AEM を再起動した後に作成された新しいセッションであることを示します。
  3. これらのセッションを開いたコードを示すスタックトレースを確認します。
  4. スタック内でアプリケーション Java パッケージを検索します。コードがアプリケーションの一部である場合は、次の節を参照してください。

III.セッションリークを修正する

JCR セッションリークを防止および修正するには:

  • コードで javax.jcr.Session を開いた場合は、必ず Session.logout() を使用して閉じます。
  • コードで org.apache.sling.api.resource.ResourceResolver を開いた場合は、必ず ResourceResolver.close() を使用して閉じます。

Session オブジェクトを閉じる

次のコードは、セッションを開いたままにします。

try {
Session session = repository.loginAdministrative(null);
Node node = session.getNode("/content/geometrixx");
  log.info("Node: " + node.getPath());
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
}

注意:

このコードは、セッションを閉じるだけでなく、repository.loginAdministrative を呼び出して開きます。このようにセッションを開く方法は、セキュリティ上の理由から、AEM の最近のリリースで非推奨になりました。

セッションを閉じるには、try/finally ブロックでコードをラップし、session.logout() を呼び出します。

Session session = null;
try {
session = repository.loginAdministrative(null);
// use session
} catch (RepositoryException re) {
log.error(re.getMessage(), re);
} finally {
if (session != null && session.isLive()) {
session.logout();
}
}

セッションを作成または共有するときは注意してください。オブジェクト間でセッションを共有すると、セッションが開かれた場所と閉じるタイミングを追跡するのが難しくなります。  また、セッションを Java スレッド間で共有しないでください。

ResourceResolver オブジェクトを閉じる

次のコードは、ResourceResolver を開いたままにします。

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  Resource resource = resourceResolver.getResource("/content/geometrixx");
  log.info("Resource: " + res.getPath());
} catch(Exception e){
log.error(e.getMessage());
}

resourceResolver を閉じるには、try/finally ブロックでコードをラップし、resourceResolver.close() を呼び出します。

try{
ResourceResolver resourceResolver = resourceFactory.getServiceResourceResolver(paramMap);
  // use ResourceResolver
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if(resourceResolver != null && resourceResolver.isLive()) {
resourceResolver.close();
}
}

重要な注意

SlingRequest または WorkflowSession を使用して取得される Session および ResourceResolver オブジェクトをアプリケーションで閉じないでください。例:

slingRequest.getResourceResolver().adaptTo(Session.class);
//または
workflowSession.getSession();

このリゾルバーとセッションは、リクエストが処理された後に自動的に閉じられます。

本作品は Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License によってライセンス許可を受けています。  Twitter™ および Facebook の投稿には、Creative Commons の規約内容は適用されません。

法律上の注意   |   プライバシーポリシー