Red Hat で Solution Architect として OpenJDK を担当している伊藤ちひろ(@chiroito)です。
この記事は、Red Hat Developerのブログ記事、Set up JDK Mission Control with Red Hat Build of OpenJDK | Red Hat Developer の翻訳記事です。
JDK Mission Controlは、Red Hat Software Collections (RHSCL)の最新メンバーとなりました。JDK Mission Controlは、HotSpotのJava仮想マシン(JVM)用の強力なプロファイラで、高度なツール群を備えています。これにより、JDK Flight Recorderが収集した広範なデータを効率的かつ詳細に分析できます。このツール群により、開発者や管理者は、OpenJDK 11を使用して本番稼働環境でローカルで実行されている、またはデプロイされているJavaアプリケーションからデータを収集・分析できます。
この記事では、JDK Mission Controlをセットアップする主な例を紹介します。Linuxでは、JDK Mission ControlはRHSCLの一部であり、Windowsでは、Red Hat Customer PortalのOpenJDKのzip配布物の一部として提供されています。 Linuxの場合、この手順ではRed Hat Build of OpenJDK 11がすでにインストールされていることを前提としています。ここでは、RHSCLからソフトウェアをインストールするためのシステムの設定方法を紹介します。これはRed Hat Enterprise Linuxの最新の開発技術を提供するものです。そして、JDK Mission Controlをインストールし、簡単なサンプルアプリケーションを実行します。チュートリアル全体の所要時間は10分以内となっています。
Mission Controlのインストール
Microsoft Windows の場合
Microsoft Windows では、Red Hat カスタマーポータルで入手できる OpenJDK の zip に JDK Mission Control と JDK Flight Recorder が含まれるようになりました。アーカイブを解凍すると、JMC バイナリは bin ディレクトリに格納されます。
Red Hat Enterprise Linux の場合
root ユーザとして subscription-manager ツールを使用して、コマンドラインからソフトウェアリポジトリを追加または削除できます。利用可能なソフトウェアリポジトリを表示するには、--list
オプションを使用します。また、RHSCL へのアクセス権があることを確認してください。
$ su - # subscription-manager repos --list | egrep rhscl
どの種類を使用するか(サーバかワークステーションかなど)によって異なります。以下のコマンドでリポジトリを有効にできます。
# subscription-manager repos --enable rhel-variant-rhscl-7-rpms
以下のコマンドでJMCをインストールします。
$ yum install rh-jmc
JMCをインストールしました。JMCと入力するか、アプリケーションメニューから起動できます。
私のように、複数のバージョンのJavaを実行していて、コマンドラインからJMCを起動したい場合は、以下のオプションを使用して、OpenJDKのRed Hat BuildへのパスでJMCを起動します。
$ scl enable rh-jmc bash $ jmc -vm /usr/lib/jvm/java-11-openjdk-11.0.2.7-0.el7_6.i386/bin
リアルタイムモニタリング
JMCでは、JVMのリアルタイムモニタリングを行えます。これを行うには、ファイルメニューから新しい接続を作成し、JVMを選択して、JMXコンソールを起動します。その結果、プロセッサ、メモリ消費量、Javaヒープ使用量、JVM CPU使用量などの概要ページが表示されるはずです。
さて、JMCの設定ができましたので、例題を実行して動作を確認してみましょう。
以下は、いくつかのファイルを読み込む簡単な例です。確かに、考慮していない問題があるかもしれません。以下の例では、2つのファイルがあります。シンプルなHTMLファイルと、約1GBのテキストファイルです。
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; public class TextFileReader { private File textFilePath = null; public TextFileReader(String textFilePath) { if (textFilePath == null) throw new IllegalArgumentException(); this.textFilePath = new File(textFilePath); } public void readFile() throws IOException { FileReader fileReader = new FileReader(textFilePath); BufferedReader bufferedreader = new BufferedReader(fileReader); StringBuffer sb = new StringBuffer(); String strLine; while ((strLine = bufferedreader.readLine()) != null) { sb.append(strLine); sb.append("\n"); } fileReader.close(); System.out.println(sb.toString()); } public static void main(String[] args) throws IOException{ new TextFileReader("index.html").readFile(); new TextFileReader("test.txt").readFile(); } }
以下のコマンドを実行して、このサンプルをコンパイルして実行してみましょう。
$ javac TextFileReader.java $ java -XX:+FlightRecorder -XX:StartFlightRecording=dumponexit=true,filename=filereader.jfr TextFileReader
上記のJavaコマンドでは,パラメータ-XX:StartFlightRecording
で,結果をfilereader.jfr
にダンプします.
このファイルをJMCで開いて、結果を見てみましょう。
JMCは、実行全体に関する掘り下げた詳細な情報を報告します。例えば、JVM内部では、GCが失速していることを示しています。さらに、メモリがあまりない上に大きなファイルでは、それは問題なので、-XX:InitiatingHeapOccupancyPercent
の値を下げるか、さらには、十分なメモリを確保する(例:Xms1024m -Xmx4096m)ことで、問題を解決できます。
また、Red HatのソフトウェアエンジニアであるJie Kang氏によるこちらでは、メソッドのプロファイリングがどのように機能し、元のコードの最適化に役立っているかが紹介されています。
JMCは、メモリリークやデッドロックなど、アプリケーションの動作を理解するのに非常に役立ちます。Red Hat Build of OpenJDK 11で試してみてください。