netail.net
自作フリーソフトや,ゲームに関する雑記を公開してます.
日記はソフトウェア工学の論文ネタが中心です.
最近のお知らせ (古いものはこちら)
2009-12-27 [長年日記] ▲
_ [研究] Java ソースコード解析 対 バイトコード解析 ▲
メソッド呼び出し関係がほしくて久しぶりに Java のバイトコード解析を試してみたので,ソースコード解析と比べた場合の違いを整理してみました.
ソースコードとバイトコードの解析の違いを特徴づけるコード例は,以下のようなものがあります.
String name = target.getClient().getName();
このソースコード断片を含むファイルを解析してメソッド呼び出し関係を調べようという場合,まず target
変数の宣言を参照してクラス名を解決し,そのクラスのコードから, getClient()
メソッドのシグネチャを取得し,その戻り値の型あるいはその親クラスに getName()
メソッドが宣言されているかどうかを調べる必要があります.一方,コンパイル後のバイトコード上では,メソッド呼び出しの情報はすべて invokevirtual
などの命令に格納されていますので,別ファイルをいちいち参照しなくとも,コンパイル後のクラスファイル単体で,呼び出し先のメソッドの情報を獲得することができます.
当たり前のことと言われればそれまでですが,ソースコードとバイトコードの解析の大きな違いの1つは,ソースコード上での「他のソースファイルへの参照」が,バイトコード上では Java コンパイラによって解決済みの情報となっているという点です.
ソースコードとバイトコードの解析の違いには,以下のようなものが挙げられます.
- コメント
ソースコード上にのみ存在する情報です.バイトコード解析では,参照することができません.
- 制御構文情報
ソースコードに対して構文木を構築することで,制御構文の入れ子関係などにアクセス可能です.バイトコード上では,いわゆる
IF
とGOTO
からなる簡単な構造に変換されています.制御フローグラフを構築するにはバイトコードのほうが簡単ですが,break
やcontinue
などの出現が,ループの終了条件判定などと区別できない可能性があります. - 厳密なソースコード位置
バイトコードがどのソースコードに対応するかについては,実行可能な命令についてのファイル名と行番号の対応関係しか保存されません.1行に複数の文が並んでいるものを区別したい場合や,宣言(実行可能な命令を伴わない文)の位置情報がほしい場合には,ソースコードの構文解析が必要です.
- メソッド呼び出し
バイトコード上では,1つのクラス単体で,呼び出し対象のメソッドのシグネチャが取得可能です.一方,ソースコードの場合,別ファイルの情報を参照しなくてはなりません.大規模なプログラムを解析するとき,下手に実装するとメモリが不足しがちになるほか,必要なファイルが足りない場合への対応方法も考えておく必要があります.
- 動的束縛の解決
どちらの解析手法の場合も,動的束縛の解決可能性を調査するには,プログラムに含まれるすべてのクラスについて,メソッドシグネチャと階層情報を集める必要があります.バイトコード解析のほうが,JARファイルから列挙すればよいので,実装が容易です.
- 型名の解決
ソースコード上では,参照可能なファイル集合の中から,型名を解決する必要があります.Java の場合,
import
文でのワイルドカードの存在や,内部クラスの取り扱いのおかげで,自作するのはかなり大変です.一方,バイトコード上では,コンパイラが解決した完全限定名を利用することができるので,各クラスを個別に解析していくことができます.ただし,ソースコード解析のほうも,正確な結果が得られなくてもかまわない場合には,1クラスだけから可能な限り型推論する手法などの適用を検討する価値があると思います. - 不正なファイルへの対処
ソースコードの場合,Java のバージョンによって文法が変更されているので,それによって生じるコンパイルエラーへの対処が必要ですし,また,誤ってコンパイルエラーのあるファイルが投入される可能性もあります.バイトコードの場合は,異なるJDKバージョン用にコンパイルされているファイルや,デバッグ情報が付与されていないものに対処する必要があります.
- 言語仕様とコンパイラ実装への依存性
バイトコード解析の結果は,言語仕様上規定されていないような式の評価順序について,コンパイラが勝手に選んだ順序を反映していることがあります.また,コンパイル時点で適用された最適化の結果を反映することがあります.
ソースコード解析とバイトコード解析のどちらかが一方的に有利ということはありません.しかし,ソースコード解析のほうが実装の手間が大きく,また構文解析などの処理コストも無視できないので,個人的な好みでいうと,型情報などは事前にライブラリからバイトコード解析で抽出しておき,対象プログラムのソースコード解析は必要最小限に抑えるという方法を採用したいところです.
2009-11-29 [長年日記] ▲
_ [VolumeDeskbar][お知らせ] Volume Deskbar 1.1.2 リリース ▲
ホットキーでミュート切り替えができるようになりました.先月にこの要望出してくださった方,お待たせしておりました.
例によって,32ビット版のみの提供です.64ビットの Explorer には32ビットでコンパイルした DLL はリンクできないので,64ビット版OSでは使えません.Delphi の 64ビットコンパイラが出るのを信じて待っていてください.Visual C++ や C# を使っての COM プログラミングのやり方とかの知識がちょっと足りてませんので,言語またいでの新バージョン開発というのはできてません.
2年ぶりの更新なんですけど,残念ながらそれだけの更新です.いくつか他にもトラブル報告はいただいていますが,手元での状況再現がうまくいかなくて,どこに問題があるのかが把握できていない状態です.そのうちログ記録バージョンとか作るかもしれません.
2009-11-21 [長年日記] ▲
_ [近況] ASEから帰ってきました ▲
主目的はワークショップ開催だったんですが,ASEも全参加してから帰ってきました.
ASEは,形式手法またはツール系,というイメージがあったんですが,今年は,テストと欠陥検出が多かった気がします.2日目の基調講演の人が「Instrumentation-based Verification」という,完全な検証ではなく,モデルのある一定のカバレッジ範囲だけを検証するという方式を説明してました.モデル上でテストしてるだけとも言えなくはないですが,形式的検証よりも現実的なアプローチという印象はありました.
また,欠陥検出のほうは,ライブラリのメソッド呼び出し順序の誤りを検出しようというネタが,静的解析・動的解析それぞれの手法が採録されています.わりと長いこと研究されてるネタではありますが,Tao Xie とか Andreas Zeller のグループが着実に成果を積み重ねている気がします.
今回の収穫:動的解析において,あるオブジェクトの使用方法が "typical" であるかどうか,というのを調べるのに,1プログラムで発見した使用方法が,別のプログラムでも発見できるか,というのを調べている研究がありました.この評価方式は使えそうです.
2009-10-12 [長年日記] ▲
_ [hyCalendar][お知らせ] hyCalendar 1.6.4 リリース ▲
カレンダーのフォント設定のうち「文字セット」情報を保存していなかった問題を修正しました.
文字セットの保存を忘れていたので,hyCalendar は欧文系のフォントであっても日本語文字セットを使おうとしてしまい,存在しないフォントのかわりにデフォルトのフォント(おそらくMS P ゴシック)を使って画面を描画してしまうという症状が出ていました.
このバグはフォント設定できるようになってからずっと生き残ってたと思います.ご迷惑をおかけしました.
2009-09-18 [長年日記] ▲
_ [近況][ツール] ToroisePlink が putty の接続設定に引きずられる ▲
PlinkとTortoisePlinkは,どうやら起動時にputtyの「標準の設定」を見に行って,ホスト名が入ってたらそこに自動で接続しにいくようです.TortoiseSVNからこれらを使用してsvn+sshでチェックアウトしようとしたとき,ネットワークで接続しにいこうとはするが,接続が閉じてしまってうまく動かないというエラーになってしまいます.
他のコマンドラインオプションに優先してとりあえず標準ホストに接続しにいくというのは,かなり豪快な設計という気がしました.加えて,TortoisePlink の接続先=標準の設定の接続先でも失敗するあたり悲しいところです.Plinkの内部状態が,TortoiseSVN側が期待しているような状態じゃないせいだろうとは思いますが…….
2009-08-27 [長年日記] ▲
_ [読書] メモリ節約のパターン本 ▲
11月にワークショップのKeynoteとして来てくれるらしい James Noble が書いてる 省メモリプログラミングを読んでみました.内容的には知ってることも多い本です.個々の話題については知ってるからこそパターンだという話もありますが,カタログ化,パターン間の関係の明記あたりには価値のある本です.読んで勉強するためというより,手元に置いといて必要に応じて読み返すリファレンスマニュアル的な本だという気もします.
パターンを適用することによるトレードオフの分析もしっかり行われていますが,全体的には,メモリを節約する以上,処理時間やプログラマの労力を犠牲にする方向に傾いてます.そういえば,逆方向,つまりメモリをがんがん使って速度,安全性,保守性を上げるという富豪的プログラミング手法はあんまり見ませんね.資源は使おうと思えばいくらでも使うことができて,たとえば Omniscent Debugging(全実行履歴・メモリ状態を保存したデバッグ)は,富豪的な発想ではありますが,デバッグに全メモリ資源を使い尽くしてしまいます.そこまで行き過ぎない「浪費家ではない富豪的プログラミング」のパターンとかないもんでしょうか.
_ ryo [本当に素晴らしいソフトなので64ビットに対応することを期待しています。 頑張って下さい!]