情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

Eclipseデバッグ効率化!無駄なステップ実行を減らす「Step Filter」の設定方法

Eclipse (60) Java (38) デバッグ (3)

Eclipseの「Step Into」の挙動が設定によって変更できることを知っていましたか?

今回は、「Step Into」を始めとする「Step実行」の挙動を変更する「Step Filtering」の設定方法と利用例を紹介します。使えるかも、と思ったら人は、ぜひ導入を検討してみてください。

「Step Into」とは

「Step Into(F6)」は、プログラムを1行ずつ実行する操作で、デバッグ時に利用します。

そして、メソッドを呼び出す行では、メソッドの中にジャンプして、1行ずつ実行します

「そこに潜らなくてもいいのに!」

したがって、「Step Into」を使えば、1行ずつプログラムの動きを確認できるのですが、「今はそのコードを見たい訳じゃない」とか「汎用ライブラリの中はすっ飛ばして欲しい」「またsetter/getterか」と思うことがあります。

つまり、「不要な部分は飛ばして欲しい!」のです。

逆に「なぜか勝手にコードが飛ばされてる!?」と思った場合はこちら

解決策:Step Filtering

実は、「Preference>Java>Debug」に、「Step Into」でジャンプする先をフィルタできる「Step Filtering」という設定が用意されています

有効化

まず、「Step Filtering」を有効にするために「Use Step Filters」を「ON」にします。

フィルタ設定

そして、「Defined step filters」にて、除外したいクラスやパッケージをフィルタとして登録することができます

その他の設定

そのほかに、次のような設定が用意されています。

  • Filter synthetic methods (requires VM support)
  • Filter static initializers
  • Filter constructors
  • Filter simple getters
  • Filter simple setters
  • Step through filters

使い方

具体的な設定例を3つ挙げて、使い方(特に重要なところ)を説明します。

設定例1:どうでもいい標準ライブラリのコードに飛ばないようにする

問題

「this.method(rnd.nextInt());」のような、「メソッドの返値をメソッドに渡す」コード上でStepIntoをすると、まず「Random#nextInt()」に飛んでしまいます。本当は「this.method」の中に飛びたかったのに、nextIntから戻ってもう一度StepIntoし直す必要が出てしまいます。

対策:無視するクラスを設定する

そこで、「Random」のコードには飛ばないように、「java.util.Random」フィルタや、「java.util.*」フィルタを追加してあげることで、直接this.methodへジャンプできるようになります

設定例2:ClassLoaderへのStep Intoを回避する

設定例1の応用です。

問題

「this.method(new MyClass());」のような「new」を含むコードに「Step Into」すると、一見「MyClassのコンストラクタ」に移動してくれそうですが、実はクラスの情報を取得するために「ClassLoader」に入ってしまいます(初回のみ)。

デバッグ上、ClassLoaderに侵入するのは不要なことが多いため、設定で回避してしまいましょう。

対策:ClassLoaderをフィルタする

この場合は「java.lang.ClassLoader」フィルタを有効に設定しておけばOKです。これで、直接コンストラクタに飛べるようになります

(※後述の「Step through filters」が「ON」の場合は、「java.lang.Throwable」に到達してしまうので「java.*」などのフィルタも有効にしておくと便利です。

設定例3:単純なgetter/setterを無視する

最後にgetter/setterについて。

問題

getterやsetterを何度も見に行くのは無駄になることが多いです。

対策

これは「Filter simple getters」と「Filter simple setters」をONにすることで回避できるようになります。

重要設定:「Step through filters」

特別重要な設定に「Step through filters」というものがあるので紹介しておきます。

OFFのとき

この設定が「OFF」の場合は、完全にフィルタに指定したコードには立ち入らないようにStep Intoします。「Step Filter」の挙動として自然な気もします。しかし、デフォルトでは「ON」になっています。

ONのとき

では「ON」のときはどうなるかというと、フィルタ対象のコードから、フィルタの対象外のコードが呼び出されていた場合は、フィルタ対象のコードを通過した先のフィルタ対象外のコードへ飛ぶという挙動をします。

たとえば自分のコード(Main)上で、自作クラス(MyElement)を格納するためにTreeSet(HashSetの一種)を使った場合を考えます。そして、TreeSetをフィルタに登録済みとします。

TreeSetのようなCollectionインターフェースを実装したクラスは、保存したオブジェクトのequalsなどを呼び出します。つまり、例えば「自分で書いたコード(Main)」→「TreeSetのadd」→「自作クラス(MyElement)のequals」のように呼び出されるわけです。

このとき、「Step through filters」が「OFF」の場合は、「Step Into」すると、「TreeSetのadd」がフィルタされ、「自作クラスのequals」を使ったことには気がつきません。つまり、TreeSetの巻き添えをくって、自作クラスのequalsもフィルタされてしまったのです。

一方で「ON」に設定すると、TreeSetのコードはフィルタされるものの、そこから呼び出される「自作クラスのequals」はフィルタされず、equalsの1行目にジャンプします。

「Step Over」「Step Return」で十分では?

「Step Over (呼び出し先にジャンプせずに次の行まで実行)」や「Step Return(呼び出し元の行に戻る)」を使えば結構制御できると思うかもしれませんが、これは使い分けが大切だと思います。

特に、Step OverとStep Returnだけでは遠回りになってしまうステップ実行を近道するために「Step Filter」を使うと良いと思います

「this.method(new MyClass(), rnd.nextInt());」たとえばステップ実行時にこんな行をStep Intoするとき、「this.method」の中身を見たい!と思ったら、「MyClassのコンストラクタに潜る」→「Step Returnで戻る」→「Random#nextIntに潜る」→「Step Returnで戻る」→「やっとthis.methodに潜る」と、だいぶ遠回りしてしまいます。

1度や2度ならよいのですが、ループの中などで何度も実行される場合や繰り返し似たようなコードが登場する場合には、「Step Filter」を上手く設定して、直接this.methodに潜れるようにする、なんて使い方がよいと思います。

必要に応じて切り替えるのもあり

Step FiltersのON/OFFの切り替えは「Shift+F5」でも可能です。

まとめ

今回はあまり知られていないであろう「Step Filter」という設定を紹介しました。劇的に変わるものではありませんが、繰り返し行う作業を効率化するという意味では、長い目で見たらデバッグが大きく効率化されるのではないでしょうか。特に、関心のあるソースコード以外へジャンプさせられることを避けるのは、頭の中の意識が分散してしまわないようにするのにも役に立つのではないでしょうか。

初期設定のままでも、「Step Filter」を有効にしてみると良いかと思います。

コメント(0)

新しいコメントを投稿