Java 8時代の開発者のためのデバッグ/トラブル解決の基本・応用テクニック〜JJUG CCC 2014 Springまとめリポート(後編)(2/3 ページ)

» 2014年10月15日 18時00分 公開
[山本裕介株式会社サムライズム]

Java IDEのデバッガー活用の必要性

 サムライズムの山本裕介氏は「Javaデバッガ活用術 〜勘デバッグ・printデバッグから抜けだそう〜」と題して講演。Java IDEのデバッガー活用の必要性を訴えた。

 Javaアプリケーションの開発をする際、Eclipse、NetBeans、IntelliJ IDEAといったIDEを使って開発するのはもはや常識だが、デバッグについては昔ながらの「printデバッグ」(プログラムの各所にprint文を織り込んでプログラムを実行する)や、「勘でデバッグ」(コードを眺めて問題箇所を見つけ出す)をする場面は非常に多いのではないだろうか。

 printデバッグは非効率なだけではなく、デバッグが完了した後print文を消すのを忘れたままビルド、本番環境へのデプロイを行ってしまい標準出力/ディスクがあふれてしまうというトラブルもよく聞かれる。また漠然とコードを眺めてバグを見つけ出すのが困難なことは自明だ。

 山本氏は、まず「行ブレークポイント」「ステップ実行」「即時評価」「実行中の値の書き換え」といったデバッガーの基本機能を紹介した上でEclipse、NetBeans、IntelliJ IDEAそれぞれのIDEで実際にデモを行った。スライドにまとめられた各IDEのショートカット一覧は現場でも役立つのではないだろうか。

各IDEのデバッガー関連ショートカット

 ループ内をデバッグする際、不必要なタイミングで繰り返しブレークしてしまい何度も実行再開をしなければいけないという煩わしさから、効率的にデバッグができずにprintデバッグに頼ってしまう人は多い。この問題は「ヒットカウント/条件付きブレークポイント」を活用することで望みのタイミングでブレークさせることができるという小技を披露した。どのIDEでも利用できる便利なテクニックだ。

Eclipseでヒットカウント/条件付きブレークポイントを設定する方法

 また、デバッガーをそれなりに活用している開発者もデバッグ対象はIDE内から起動するプロセスのみで、アプリケーションサーバーなどのコンテナー上で発生するバグについては再現条件を想像しながらテストケースを書き、再現に成功したらユニットテストをデバッグ実行するという人も多い。

 リモートデバッグは設定が難しそうで敬遠されがちだが、IDE外のJVMプロセスにアタッチしてデバッグするリモートデバッグの設定方法をIDE別に丁寧に説明した。

IntelliJ IDEAからデバッガーをアタッチさせる設定
プロダクション環境をデバッグする際はパフォーマンス低下に注意
プロダクション環境をアタッチ可能にする際はセキュリティリスクも考慮の必要がある

 最後に山本氏は、なかなか再現方法が分からない現象や、タイミングに関わるバグをデバッガーで解析するのは難しいためJavaアプリケーションの実行状況を記録して、後から巻き戻し再生しながら解析できるChronon ystems社の「Timetravelling Debugger」「Recording Server」を紹介した。

Java 8より導入された新しいメモリ領域を使いこなすためのテクニック

 JVM監視・解析ツール「HeapStats」の開発者であり、OpenJDK自体の開発にも参加していることからJVMを中から知り尽くしている末永恭正氏は講演「MetaspaceをOpenJDK実装からみてみよう!」において「Metaspace」をOpenJDKのコードレベルから解説した。

JavaのイベントでC++のコードを非常に楽しそうに解説する末永氏

 「Metaspace」はJava 8より導入された新しいメモリ領域で、オラクルが買収したBEA Systems社が持っていたJVM「JRockit」のメモリ管理方式に由来する。いわばJava 7までのPermanent領域に代わるものだ。

JRockitの流れを汲んでPermanent領域を廃止した「HotRockit」

 Permanent領域はJVMが確保するメモリのうち、クラス定義などを格納する領域でOutOfMemoryErrorの原因として多くのエンジニアを悩ませてきた。Permanent領域はデフォルトの最大サイズが64MB程度(プラットフォーム、JVMにより異なる)と小さく、アプリケーションの再デプロイ時やクラスがリークしている場合にOutOfMemoryErrorが発生する。

 OutOfMemoryErrorの対処としておなじみの「-Xms」「-mx」オプションの指定ではPermanent領域の枯渇は解決しないため、対症療法的に定期的にJVMの再起動をして回避してしまうケースも見られる。対してMetaspaceは実質無制限になっているため「ちょっとアプリケーションの規模が大きい」程度ではOutOfMemoryErrorは発生しなくなった。

Metaspaceは内部的に連続したメモリ領域ではない。最大ヒープサイズが32GB以下の場合は「CompressedClassSpace」という領域にクラス情報を圧縮して格納

 一方で、64MB制限のPermanent領域が制限なしのMetaspaceに移行したことでメモリを気にする必要がなくなったわけではない。大きなアプリケーションのロードや、再デプロイ時の一時的なPermanent領域不足の心配はなくなったが、クラスがリークしていればCompressedClassSpaceの最大サイズに達してやはりOutOfMemoryErrorが発生したり、プロセスサイズの肥大からOSやOutOfMemory Killerにプロセスを消されたりする可能性がある。

 そこで末永氏は、さまざまなツールによるMetaspaceの解析、監視方法を紹介した。手軽に調べるにはjcmdコマンドが良さそうだ。

jcmdツールによるMetaspace/metaClassSpaceサイズの確認(二つ目の引数はプロセスID。プロセスIDは引数なしでicmdコマンドを実行すると分かる)

 最後に末永氏は、Metaspaceのチューニング方法として、デフォルトの「CompressedClassSpaceSize」は1GBと大きく確保されるため絞り気味に、不安を抱えたくなければ「CompressedClassPointers」(ヒープサイズが32GB以下の場合はデフォルトで有効)を明示的に無効にするテクニックを紹介した。

あえてチューニングするのであればこのように設定

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。