java.lang.OutOfMemoryError: Metaspace について

Java1.8以降、ColdFusionでロードしたファイル(.cfmや.cfcファイルなどをリクエストしたファイル)や内部エンジンのTomcatやJDK自身が起動等にて読み込んだクラスファイルなどをメモリに格納する領域が Permanent領域(ヒープの一種)から Metaspace領域(ネイティブメモリ)へと変更されました。

これにより、JVMのヒープの一部として割り当てられていたものがOSの領域で作成されるため、従来よりもサイズの上限の意識が緩和される状況となりました。しかし、無尽蔵にネイティブメモリを使用されることを防ぐため、上限値を定める「-XX:MaxMetaspaceSize」の設定があり、ColdFusion ではデフォルトで 192 MB が割り当てられています。

「java.lang.OutOfMemoryError: Metaspace」は、設定された上限に達しMetaspaceが足りなくなった場合に発生するエラーで、ColdFusionの実運用環境でしばしば発生したとの報告があります。Metaspaceに関する説明や不足する仕組みなどは、下記のSlideshareの資料が参考になります(記事はOpenJDKの実装から見ているため、ColdFusionがサポートしているOracleJDKとは異なる事も考えられますが、動きやOutOfMemoryに遭遇した際の動作は参考になります)
https://www.slideshare.net/YaSuenag/metaspace

 

【OutOfMemoryの症状について】
  1. 上記の資料の内容から紹介すると、普段MetaspaceはGCを起こさず、ヒープ側のGCによってクラスローダーが破棄されると、関連するMetaspaceも破棄されるようです。それまでの間は、割り当て済みのMetaspaceのメモリ、あるいはMetaspaceのサイズを拡張して、新たにロードしたクラスファイルなどをメモリに格納していきます
     
  2. Metaspaceの上限サイズまで使い切ってしまうと、新たなサイズの拡張が行えない状態となり、GCを発生して使われていないクラスローダーを回収してMetaspaceの領域を確保しようとする動きになります。しかし、ほとんど解放されず新たにロードしたクラスファイルをメモリに格納できないような場合は、さらにソフト参照も回収対象としてできるかぎりクラスローダーを回収しようとします。この動きの過程の中でOutOfMemoryが発生する模様です

上記2.の状態になると、高いCPU負荷と無応答時間(30秒以上の報告あり)が発生します。また、特定のページ画面が表示されない(正常に動作する.cfmページとしない.cfmページがある)などの現象が発生する場合もあります。また、一時的にMetaspace領域が開放されても、同じアプリケーションを引き続き動作させている以上は、読み込むクラスファイルも同じであるため、必然的にOutOfMemoryが発生する状況を繰り返し、結果ColdFusionアプリケーションの動作が不安定な状態が不規則な状態になることを招きます。

 

【発生頻度について】

実稼働環境で運用されているアプリケーション(つまり、作成した.cfmや.cfcの規模、一時ファイル等の作成頻度など)に依存するため、一概にすべての環境で現象が発生するとは限りません。ただし、旧バージョンから新バージョンへ移行した場合などでも発生する場合がある模様です。この要因には、ColdFusionをバージョンしたことによって、新たな機能(CF関数)やライブラリが追加され、以前のバージョンよりもリソースが増加していることが考えられます。また、後述のJava1.8以降で確認されている問題によって、Metaspaceが多く消費されることが要因になる可能性もあります。

 

【対応について】

旧バージョンからそのまま移行したり、必要の応じてアプリケーションを作成している以上、アプリケーション自体を改修して対応していくことは困難だと思われますので、まずは、Metaspaceの上限を増やすことで、現象の回避が可能かを検討してください

【注意】 OSのメモリ使用量に余裕があることを確認してください。
仮想OS環境など、割り当てメモリ量に余裕がない場合はメモリの増加を検討ください。

「参考手順」

  1. ColdFusionのAdministratorにログインして、[サーバーの設定] > [JavaとJVM]のJVM引数にある「-XX:MaxMetaspaceSize=」の設定値を確認します
     
  2. 現在設定されている「-XX:MaxMetaspaceSize=」の値を増やします。初期値は192MBです。初期値の場合は、2倍~3倍程度(576MB)に変更してください。初期値以外の場合は、OSのメモリ使用量に注意しつつ、現在の設定値よりも多いサイズに変更してください
     
  3. 設定の変更後、ColdFusion を再起動します
    • Metaspaceの変更を反映するためにColdFusion の再起動が必要となりますので、運用中のサービスに影響がないタイミングに作業を行ってください
       
  4. 再起動後、アプリケーションの動作を確認し、引き続き OutOfMemoryError: Metaspace が発生    する場合は、さらにMaxMetaspaceSizeの値を増やします。

 

【Metaspaceの計測について】

ColdFusion側ではMetaspaceのサイズを計測する方法はありません。GC.logを取得するようにJVMパラメータを追加して、FullGCが発生したりMetaspaceのOutOfMemoryが再発した時のMetaspaceのサイズの推移を確認する方法や、Javaのjconsoleを使用して確認する方法などを検討してください。

【参考サイト】
https://nimitsharma.wordpress.com/2013/04/25/how-to-configure-jconsole-with-coldfusion/
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/management/jconsole.html


「参考手順」

  1. JDK1.8をインストールします
    • jconsoleを使用するには、JDKのインストールが必要です(ただし、ColdFusionが使用するJVMを変更する必要はありません)
       
  2. Java設定ファイルをバックアップします
    • [CF_root]/cfusion/bin/jvm.config
       
  3. ColdFusion Administrator の [サーバーの設定] >「JAVAとJVM」を選択し、JVM引数の「-server」の後に以下の設定例の文字列を追加します。
    • 設定例
      -Dcom.sun.management.jmxremote
      -Dcom.sun.management.jmxremote.port=7900
      -Dcom.sun.management.jmxremote.ssl=false
      -Dcom.sun.management.jmxremote.authenticate=false
      ※項目の区切りは半角スペースで一行で記入し、改行はしないで下さい
       
  4. jconsole.exe(手順1で追加したJDKのbinフォルダ内)を起動してリモート・プロセスを選択し、サーバーのアドレス(同じPCであればlocalhostや127.0.0.1)と指定したポート(上記の例では7900)を指定して(「localhost:7900」等)接続します。
    • 上記3.の設定例ではユーザー名・パスワードは不要で、SSLも不使用となります
       
  5. メモリータブのチャートで「メモリープール "Metaspace"」を選択すればグラフの値や詳細の値を確認できます
    • 運用環境に合わせて3)の設定等を変更下さい
    • 外部からの意図しない接続を避けるため、指定したポートへのアクセスはFW等で制限されることをお勧めいたします

 

【上記以外の対応について(2019/11 追加)】

下記の「ColdFusion のパフォーマンスに関する問題とトラブルシューティング」のページの最後にXML解析によってパフォーマンスに影響がでる場合の説明があります。

1 つまたは 2 つの事例に別の問題が発生しました。XML 解析によってパフォーマンスに影響が出る場合は、以下の jvm 引数で修正できます。
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true

https://helpx.adobe.com/jp/coldfusion/kb/coldfusion-performance-issues-troubleshooting.html

上記の問題はXMLの解析処理の問題ですが、下記の別の記事にて、この問題によって、Metaspaceの領域が不足するOutOfMemoryを引き起こすという事例が報告されております。
https://codeday.me/jp/qa/20190225/303082.html

ColdFusionの内部仕様は公開されておらず、どの処理で発生するかなどの詳細も不明なため、運用されているアプリケーションにも該当するかどうかは不明ですが、何らかのXMLに関連する処理を行われている場合や、「-XX:MaxMetaspaceSize」のサイズを増やした後も(発生頻度に違いはあれ)OutOfMemoryError: Metaspaceエラーが引き続き発生する場合には、「-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true」をJVM引数に追加することも検討ください

ColdFusion 2018では、上記のパラメーターがデフォルトで登録されています


 


記事公開日:2019年11月22日
最終更新日:2020年03月23日


x

Sample Modal Window

This is just a sample…

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent suscipit iaculis libero sed tristique. Quisque mollis dolor non tellus placerat vitae sodales lectus porta. Curabitur ut suscipit tellus. Maecenas rhoncus, ante vitae vehicula vestibulum, metus sapien dapibus tellus, et mattis dolor neque vitae nisl. Nullam eleifend ultrices ipsum eget pretium. Curabitur semper metus ut ante adipiscing nec volutpat sem rutrum. Nullam a nisi lacus, non interdum ante. Vivamus ante augue, commodo vel egestas sed, pharetra nec dui. Quisque sed tellus felis. Donec ipsum mauris, sagittis eu accumsan in, aliquam non ipsum.

Vestibulum tempor nunc nec felis scelerisque eget elementum erat dignissim. Ut vel ipsum mollis orci venenatis luctus. Aenean vehicula quam vel quam porttitor ac iaculis elit pulvinar. Proin consequat, ipsum eu venenatis semper, justo turpis posuere tortor, ac placerat metus nisl et lectus. Nulla cursus dui id nunc ullamcorper sed semper nisl lobortis. Aliquam erat volutpat. Phasellus arcu ante, imperdiet in ornare sed, laoreet eu massa.