以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
第1の実施の形態を説明する。
図1は、第1の実施の形態の解析装置の例を示す図である。
第1の実施の形態の解析装置10は、既存ソフトウェアのソースコードを解析して変数の間の依存関係を判定し、ソースコードの修正作業を支援する。以下に説明するように、解析装置10は、ソースコードの静的解析と実行ログを用いた動的解析とを組み合わせることで、データベースを介した変数の値の伝搬を追跡できるようにする。解析装置10は、クライアントコンピュータでもよいしサーバコンピュータでもよい。
解析装置10は、記憶部11および処理部12を有する。記憶部11は、RAM(Random Access Memory)などの揮発性の半導体メモリでもよいし、HDD(Hard Disk Drive)やフラッシュメモリなどの不揮発性のストレージでもよい。処理部12は、例えば、CPU(Central Processing Unit)やDSP(Digital Signal Processor)などのプロセッサである。ただし、処理部12は、ASIC(Application Specific Integrated Circuit)やFPGA(Field Programmable Gate Array)などの特定用途の電子回路を含んでもよい。プロセッサは、RAMなどのメモリ(記憶部11でもよい)に記憶されたプログラムを実行する。プログラムには解析プログラムが含まれる。複数のプロセッサの集合を「マルチプロセッサ」または単に「プロセッサ」と言うことがある。
記憶部11は、ソースコード14を記憶する。ソースコード14は、モジュール13を利用してデータベース16にアクセスするソフトウェアのソースコードである。ソースコード14は、例えば、オブジェクト指向言語などの高級言語で記述されている。
モジュール13は、例えば、オブジェクト型データと関係型データとを相互に変換するO/Rマッパーなど、データベースアクセス用のライブラリモジュールである。解析装置10は、モジュール13のソースコードを有していないことがある。また、モジュール13の挙動は、ソースコード外の独自の設定ファイルによって制御されることがある。よって、ソースコード14から見てモジュール13の内部処理はブラックボックスになることがある。データベース16は、複数のデータ項目を有する。例えば、データベース16は、データ項目として複数のカラムを有する関係型データベースである。ただし、データベース16は、複数のデータ項目を識別できるようにデータフォーマットが規定されていればよく、ツリー型やオブジェクト型などの他の種類のデータベースでもよい。
処理部12は、ソースコード14に対して静的解析を行う。このとき、処理部12は、ソースコード14から変数14a,14bおよび呼び出し文14c,14dを検出する。呼び出し文14cは、変数14aを引数として用いて、モジュール13が有する関数13aを呼び出す命令文である。呼び出し文14dは、モジュール13が有する関数13bを呼び出し、関数13bの返り値を変数14bに代入する命令文である。
関数13a,13bは、モジュール13の外部から呼び出し可能な処理単位であり、メソッド・手続き・セクションなど他の名称で呼ばれることもある。関数13aとしては、引数として受け付けた値を用いてデータベース16を更新する機能を実装した処理単位が想定される。関数13bとしては、データベース16からデータを検索して検索結果を返り値として出力する機能を実装した処理単位が想定される。
上記の静的解析では、関数13a,13bの内部処理が不明であるため、呼び出し文14cの引数がデータベース16の何れのデータ項目に対応するか不明であり、また、呼び出し文14dの返り値がデータベース16の何れのデータ項目に対応するか不明である。このため、上記の静的解析のみでは、呼び出し文14cにより書き込まれた値が呼び出し文14dにより読み出されることがあるのか、呼び出し文14cにより書き込まれる値と呼び出し文14dにより読み出される値とが無関係であるのか、判定することが難しい。
そこで、解析装置10は、このソフトウェアを実行させた場合に生成されるログを取得して動的解析を追加的に行う。好ましくは、解析装置10は、上記の静的解析の結果に基づいてログ採取位置を限定的に設定して、当該ソフトウェアを実行させる。ソフトウェアを実行する装置は解析装置10自身でもよいし他の装置でもよい。ただし、解析装置10は、上記の静的解析の前に採取されたログを使用することも可能である。
処理部12は、呼び出し文14c,14dの実行履歴を示すログ15aを取得する。ログ15aは、例えば、関数13a,13bの呼び出し元をログ採取位置に設定することで取得できる。ログ15aは、例えば、関数13aを呼び出したときに指定された引数の値や、関数13bを呼び出したときに得られた返り値を含む。
更に、処理部12は、モジュール13の制御に基づいて生成されたクエリの実行履歴を示すログ15bを取得する。ログ15bは、例えば、モジュール13またはモジュール13から利用される他のモジュールの中のクエリ生成機能をログ採取位置に設定することで取得できる。ログ15bは、例えば、生成されたクエリ文と当該クエリ文に対するデータベース16からの出力とを含む。クエリ文は、SQLなどデータベース16の種類に応じたクエリ言語で記述されている。データベース16に対する値の書き込みを示すクエリ文は、例えば、データ項目と対応付けて書き込み値を含んでいる。データベース16からの値の読み出しを示すクエリ文は、例えば、読み出す値が格納されているデータ項目の識別情報を含み、読み出された値が当該クエリ文に付加されている。
一例として、ログ15aは、引数「23」を指定して関数13aを呼び出したことを示すレコードと、関数13bを呼び出して返り値「23」を取得したことを示すレコードとを含む。ログ15bは、データ項目「c1」の値が「23」でありデータ項目「c2」の値が「0」であるデータを挿入するクエリ文を示すレコードを含む。また、ログ15bは、データ項目「c1」と「c2」の値を読み出すクエリ文を示し、読み出された値がそれぞれ「23」と「0」であることを示すレコードを含む。
処理部12は、ログ15aに含まれる呼び出し文14cの実行履歴とログ15bに含まれる書き込み時のクエリの実行履歴とを比較し、関数13aの引数に対応するデータ項目16aを判定する。例えば、処理部12は、関数13aの引数の値をログ15aから抽出し、クエリ文の中の各データ項目の書き込み値をログ15bから抽出し、引数の値と一致する書き込み値が指定されたデータ項目を検出する。
また、処理部12は、ログ15aに含まれる呼び出し文14dの実行履歴とログ15bに含まれる読み出し時のクエリの実行履歴とを比較し、関数13bの返り値に対応するデータ項目16bを判定する。データ項目16bは、データ項目16aと同一であることもあるし同一でないこともある。例えば、処理部12は、関数13bの返り値をログ15aから抽出し、クエリ文に対応する出力の中の各データ項目の読み出し値をログ15bから抽出し、返り値と一致する読み出し値が得られたデータ項目を検出する。
一例として、関数13aの引数の値として「23」がログ15aから抽出され、データ項目「c1」および「c2」の書き込み値として「23」および「0」がログ15bから抽出される。この場合、引数の値とデータ項目「c1」の書き込み値が一致するため、関数13aの引数に対応するデータ項目16aは「c1」であると判定される。また、関数13bの返り値として「23」がログ15aから抽出され、データ項目「c1」および「c2」の読み出し値として「23」および「0」がログ15bから抽出される。この場合、返り値とデータ項目「c1」の読み出し値が一致するため、関数13bの返り値に対応するデータ項目16bは「c1」であると判定される。
処理部12は、判定したデータ項目16aとデータ項目16bとが同一か否かに基づいて、変数14aと変数14bの間の依存関係を判定する。例えば、データ項目16aとデータ項目16bが同一である場合、変数14aの値は呼び出し文14cを介してデータベース16の所定のデータ項目に書き込まれ、呼び出し文14dを介してデータベース16の当該データ項目から読み出されることがある。この場合、変数14aの値は変数14bに伝搬することがあり、変数14bは変数14aの影響を受けると判定される。
第1の実施の形態の解析装置10によれば、ソースコード14から変数14a,14bおよび呼び出し文14c,14dが検出され、ログ15a,15bが取得される。ログ15aに含まれる呼び出し文14cの実行履歴とログ15bに含まれる書き込み時のクエリの実行履歴との比較に基づいて、関数13aの引数に対応するデータ項目16aが判定される。また、ログ15aに含まれる呼び出し文14dの実行履歴とログ15bに含まれる読み出し時のクエリの実行履歴との比較に基づいて、関数13bの返り値に対応するデータ項目16bが判定される。データ項目16aとデータ項目16bとが同一か否かに基づいて、変数14aと変数14bの間の依存関係が判定される。
これにより、モジュール13を利用してデータベース16にアクセスする場合であっても、関数の引数や返り値に対応するデータベース16のデータ項目を判定でき、ソースコード14の静的解析の限界を補うことができる。よって、データベース16を介した変数の値の伝搬を高精度で追跡することが可能となり、ある変数の影響を受ける他の変数の判定精度を向上できる。その結果、ソースコード14の修正作業を効率化できる。
[第2の実施の形態]
次に、第2の実施の形態を説明する。
図2は、第2の実施の形態の情報処理システムの例を示す図である。
第2の実施の形態の情報処理システムは、アプリケーションソフトウェアの既存ソースコードを修正して機能追加または機能変更を行う開発作業を支援する。情報処理システムは、解析装置100およびサーバ装置200を有する。解析装置100およびサーバ装置200は、LAN(Local Area Network)などのネットワーク30に接続されている。
解析装置100は、ユーザが使用するクライアントコンピュータである。解析装置100は、アプリケーションソフトウェアのソースコードをディスプレイに表示し、ユーザによるソースコードの修正作業を支援する。このとき、解析装置100は、ソースコードに記載された変数の間の依存関係を解析し、ある変数の影響を受けるソースコードの範囲を判定する。例えば、解析装置100は、ユーザから1つの変数が指定されると、指定された変数の影響を受ける他の変数やメソッドをソースコード上で強調表示する。また、例えば、解析装置100は、影響を受ける他の変数やメソッドのリストを表示する。
サーバ装置200は、アプリケーションソフトウェアを試験的に実行するサーバコンピュータである。第2の実施の形態のアプリケーションソフトウェアはデータベースを利用するため、サーバ装置200にはデータベースが構築されている。解析装置100の影響範囲解析では、ソースコードに加えて、アプリケーションソフトウェアを実行することで生成されるログが使用される。そこで、解析装置100からの指示に応じてサーバ装置200でアプリケーションソフトウェアが実行され、サーバ装置200で生成されたログが解析装置100に転送される。ただし、アプリケーションソフトウェアをサーバ装置200で実行する代わりに、解析装置100で実行するようにしてもよい。
図3は、解析装置のハードウェア例を示すブロック図である。
解析装置100は、CPU101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、媒体リーダ106および通信インタフェース107を有する。上記のユニットはバスに接続されている。サーバ装置200も、解析装置100と同様のハードウェアを用いて実装することができる。
CPU101は、プログラムの命令を実行する演算回路を含むプロセッサである。CPU101は、HDD103に記憶されたプログラムやデータの少なくとも一部をRAM102にロードし、プログラムを実行する。なお、CPU101は複数のプロセッサコアを備えてもよく、解析装置100は複数のプロセッサを備えてもよく、以下の処理を複数のプロセッサまたはプロセッサコアを用いて並列に実行してもよい。また、複数のプロセッサの集合を「マルチプロセッサ」または単に「プロセッサ」と言うことがある。
RAM102は、CPU101が実行するプログラムやCPU101が演算に用いるデータを一時的に記憶する揮発性の半導体メモリである。なお、解析装置100は、RAM以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
HDD103は、OS(Operating System)やアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。なお、解析装置100は、フラッシュメモリやSSD(Solid State Drive)などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
画像信号処理部104は、CPU101からの命令に従って、解析装置100に接続されたディスプレイ111に画像を出力する。ディスプレイ111としては、CRT(Cathode Ray Tube)ディスプレイ、液晶ディスプレイ(LCD:Liquid Crystal Display)、プラズマディスプレイ、有機EL(OEL:Organic Electro-Luminescence)ディスプレイなど、任意の種類のディスプレイを用いることができる。
入力信号処理部105は、解析装置100に接続された入力デバイス112から入力信号を取得し、CPU101に出力する。入力デバイス112としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、解析装置100に複数の種類の入力デバイスが接続されていてもよい。
媒体リーダ106は、記録媒体113に記録されたプログラムやデータを読み取る読み取り装置である。記録媒体113として、例えば、磁気ディスク、光ディスク、光磁気ディスク(MO:Magneto-Optical disk)、半導体メモリなどを使用できる。磁気ディスクには、フレキシブルディスク(FD:Flexible Disk)やHDDが含まれる。光ディスクには、CD(Compact Disc)やDVD(Digital Versatile Disc)が含まれる。
媒体リーダ106は、例えば、記録媒体113から読み取ったプログラムやデータを、RAM102やHDD103などの他の記録媒体にコピーする。読み取られたプログラムは、例えば、CPU101によって実行される。なお、記録媒体113は可搬型記録媒体であってもよく、プログラムやデータの配布に用いられることがある。また、記録媒体113やHDD103を、コンピュータ読み取り可能な記録媒体と言うことがある。
通信インタフェース107は、ネットワーク30に接続され、ネットワーク30を介してサーバ装置200と通信を行うインタフェースである。通信インタフェース107は、例えば、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースである。ただし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
次に、解析装置100による影響範囲解析について説明する。
図4は、解析対象のソースコードの例を示す図である。
ソースコード131は、解析対象とするソースコードの一例である。図4に示すソースコード131は、オブジェクト指向に基づく擬似的なソースコードである。ソースコード131には、「SampleClassA」,「SampleClassB」および「DBAccess」の3つのクラスが記載されている。クラス「SampleClassA」はメソッド「methodA()」を含む。クラス「SampleClassB」はメソッド「methodD()」を含む。クラス「DBAccess」はメソッド「methodB(int)」,「methodE()」を含む。
メソッド「methodA()」は、ローカル変数として整数型の変数xを有し、変数xを引数としてメソッド「methodB(int)」を呼び出している。メソッド「methodD()」は、ローカル変数として配列型の変数zを有し、メソッド「methodE()」を呼び出してその返り値を変数zに代入している。ここで使用する配列はArrayList<Bean>型であり、Bean型の要素を任意の数格納できる。
クラス「DBAccess」は、クラスメンバとして文字列型の変数bを有し、クラス「UrlMapper」を参照している。クラス「UrlMapper」は、オブジェクト型データと関係型データとを相互に変換するO/Rマッパーであり、関係データベースへのアクセスを容易にするライブラリである。クラス「UrlMapper」の挙動は設定ファイルによって別途定義されるため、ソースコード131から見てクラス「UrlMapper」の中身はブラックボックスである。
メソッド「methodB(int)」は、引数として整数型の変数aを有する。また、メソッド「methodB(int)」は、変数a,bを引数としてクラス「UrlMapper」のメソッド「methodC(int,String)」を呼び出している。メソッド「methodE()」は、ローカル変数として配列型の変数yを有し、クラス「UrlMapper」のメソッド「methodF()」を呼び出してその返り値を変数yに代入している。また、メソッド「methodE()」は、変数yの値を返り値として呼び出し元に対して出力している。
図5は、データベースを介した影響範囲の例を示す図である。
ここでは、上記のソースコード131に記載された複数のメソッドの間の呼び出し関係をグラフで表現している。メソッド132aは「methodA()」であり、整数型の変数xを有する。メソッド132bは「methodB(int)」であり、整数型の変数aを有する。メソッド132aは、変数xを引数として用いてメソッド132bを呼び出している。メソッド132cは「methodC(int,String)」であり、整数型の変数aと文字列型の変数bを有する。メソッド132bは、変数aを引数として用いてメソッド132cを呼び出している。
また、メソッド132dは「methodD()」であり、配列型の変数zを有する。メソッド132eは「methodE()」であり、配列型の変数yを有し、変数yの値を返り値として用いる。メソッド132dはメソッド132eを呼び出し、その返り値を変数zに代入している。メソッド132fは「methodF()」である。メソッド132eはメソッド132fを呼び出し、その返り値を変数yに代入している。
メソッド132c,132fはO/Rマッパーのメソッドであり、メソッド132c,132fが呼び出されると何段階かのメソッド呼び出しを経由してJDBC(Java(登録商標) Database Connectivity)メソッド132gが呼び出される。JDBCは、関係データベースとコネクションを確立し関係データベースに対してクエリを発行するモジュールである。JDBCメソッド132gが呼び出されると、データベーステーブル132hを操作するSQL文が出力される。以下の説明では、データベーステーブル132hの名称を「T1」と表記することがある。データベーステーブル132hは、カラムc1,c2,c3を有する。
第2の実施の形態では、メソッド132cを経由するメソッド呼び出しに応じて、JDBCメソッド132gは、データベーステーブル132hにレコードを挿入するSQL文(insert文)を出力する。挿入されるレコードのカラムc1の値はメソッド132cの変数aの値であり、カラムc2の値はメソッド132cの変数bの値である。カラムc3の値は変数a,bの値に依存しない。また、メソッド132fを経由するメソッド呼び出しに応じて、JDBCメソッド132gは、データベーステーブル132hからレコードを検索するSQL文(select文)を出力し、検索されたレコードを取得する。取得する各レコードにはカラムc1,c2の値が含まれる。
ここで、ソースコード131の静的解析によれば、メソッド132aの変数xがメソッド132bの変数aに影響を与え、メソッド132bの変数aがメソッド132cの変数aに影響を与えることを検出できる。すなわち、メソッド132cの変数aはメソッド132bの変数aに依存し、メソッド132bの変数aはメソッド132aの変数xに依存する。また、静的解析によれば、メソッド132fの返り値がメソッド132eの変数yに影響を与え、メソッド132eの変数yがメソッド132dの変数zに影響を与えることを検出できる。すなわち、メソッド132dの変数zはメソッド132eの変数yに依存し、メソッド132eの変数yはメソッド132fの返り値に依存する。
しかし、ソースコード131の静的解析だけでは、メソッド132c,132fより先のメソッド呼び出しを追跡できない。このため、メソッド132cの変数a,bが、関係データベースを介してメソッド132fの返り値に影響を与えるか否か判定できない。実際には、メソッド132cの変数a,bは、データベーステーブル132hのカラムc1,c2を介してメソッド132fの返り値に影響を与えている。よって、メソッド132aの変数xはメソッド132dの変数zに影響を与えることになる。
このような関係データベースを介した変数の依存関係を解析するため、解析装置100は、ソースコードを用いた静的解析とログを用いた動的解析とを組み合わせて実行する。解析装置100は、サーバ装置200にソフトウェアを実行させ、追跡不能であるメソッド132cを呼び出すメソッド132bのログと、追跡不能であるメソッド132fを呼び出すメソッド132eのログとを採取する。また、解析装置100は、クエリを発行するJDBCメソッド132gのログを採取する。ログを採取する位置は上記の位置に限定することができる。そして、解析装置100は、後述する方法によってログを解析し、メソッド132cの変数a,bとメソッド132fの返り値との間の関係を判定する。
ログの採取は、例えば、次のような方法で行われる。解析装置100は、ソースコード131をコンパイルしたコンパイル済みのアプリケーションプログラムをサーバ装置200に配置する。また、解析装置100は、ログの採取方法を示すエージェントプログラムを作成してサーバ装置200に配置する。解析装置100は、アプリケーションプログラムを起動するためのコマンドをサーバ装置200に送信する。このとき、解析装置100は、コマンドにオプションを付与して、アプリケーションプログラムにエージェントプログラムが挿入されるようにする。エージェントプログラムの挿入は、起動時にプログラムを部分的に書き換えるバイトコードインジェクションの技術を用いて実現できる。すなわち、サーバ装置200は、アプリケーションプログラムをRAMにロードする際に、エージェントプログラムに従ってアプリケーションプログラムを書き換える。これにより、ソースコード131を改変せずに、指定した位置でログを採取することができる。
なお、第2の実施の形態ではデータベースとして関係データベースを使用したが、XML(Extensible Markup Language)データベースなど他の種類のデータベースを使用してもよい。使用するデータベースは、複数のデータ項目が予め定義されており、所定のフォーマットのクエリによってデータ操作が行われるものであればよい。その場合、JDBCに代えてデータベースの種類に応じたモジュールを用いてコネクションが確立される。
次に、影響範囲解析の手順について説明する。
図6は、影響テーブルの例を示す図である。
解析装置100は、ソースコード131の静的解析により影響テーブル141(テーブル1)を生成する。影響テーブル141は、影響元の変数について、変数名、クラス名、メソッド名および変数型の項目を有する。また、影響テーブル141は、影響先の変数について、変数名、クラス名、メソッド名および変数型の項目を有する。変数名は、メソッドで使用されているローカル変数の名称である。クラス名は、メソッドが属するクラスの名称である。メソッド名は、メソッドの名称である。変数型は、変数の型である。
影響テーブル141には、2つの変数の間の直接的な影響関係(依存関係)が登録される。影響テーブル141に登録された複数の影響関係を連鎖的に組み合わせることで、ある変数の影響を受ける他の変数の範囲を判定することができる。
例えば、影響テーブル141には、メソッド「methodA()」の変数xが影響元、メソッド「methodB(int)」の変数aが影響先である影響関係が登録される。また、メソッド「methodB(int)」の変数aが影響元、メソッド「methodC(int,String)」の変数aが影響先である影響関係が登録される。また、メソッド「methodF()」の返り値(return)が影響元、メソッド「methodE()」の変数yが影響先である影響関係が登録される。また、メソッド「methodE()」の変数yが影響元、メソッド「methodD()」の変数zが影響先である影響関係が登録される。なお、図6では、「methodC(int,String)」と「methodF()」のソースコードが存在せず追跡不能であるため、そのクラス名を「DBAccess」として記載している。
図7は、未追跡テーブルの例を示す図である。
解析装置100は、ソースコード131の静的解析によって、上記の影響テーブル141と併せて未追跡テーブル142(テーブル2)を生成する。未追跡テーブル142は、ソースコード131の中に定義されておらず静的解析で未追跡となったメソッドを示す。未追跡テーブル142は、クラス名、メソッド名および呼び出し元の項目を有する。クラス名は、呼び出し元が属するクラスの名称である。メソッド名は、未追跡であるメソッドの名称である。呼び出し元は、未追跡のメソッドを呼び出したメソッドの名称である。
例えば、未追跡テーブル142には、クラス「DBAccess」のメソッド「methodB(int)」が、メソッド「methodC(int,String)」を呼び出したことが登録される。また、クラス「DBAccess」のメソッド「methodE()」が、メソッド「methodF()」を呼び出したことが登録される。
図8は、呼び出しログテーブルの例を示す図である。
解析装置100は、未追跡テーブル142に登録された呼び出し元におけるログ(呼び出しログ)をサーバ装置200に採取させ、サーバ装置200から呼び出しログを取得する。解析装置100は、取得した呼び出しログから動的解析に使用するデータを抽出して呼び出しログテーブル143(テーブル3)を生成する。呼び出しログテーブル143は、クラス名、メソッド名、時刻、引数および返り値の項目を有する。
クラス名は、呼び出し元が属するクラスの名称である。メソッド名は、呼び出された未追跡のメソッドの名称である。時刻は、未追跡のメソッドが呼び出された時刻である。引数は、呼び出し先のメソッドに渡した引数の値である。引数のないメソッドを呼び出した場合は引数はnullとなる。返り値は、呼び出し先のメソッドから取得された返り値である。返り値のないメソッドを呼び出した場合は返り値はnullとなる。
一例として、アプリケーションソフトウェアを実行することで、メソッド「methodC(int,String)」が3回呼び出され、メソッド「methodF()」が1回呼び出されたとする。「methodC(int,String)」は、時刻11:22:33に引数の値を(50,α)として呼び出されている。また、時刻11:22:43に引数の値を(35,β)として呼び出され、時刻11:22:55に引数の値を(20,γ)として呼び出されている。「methodF()」は、時刻11:27:59に呼び出され、返り値として{(50,α),(35,β),(20,γ)}という配列が取得されている。なお、配列の要素である(50,α),(35,β),(20,γ)はそれぞれBean型のオブジェクトである。
図9は、DBアクセスログテーブルの例を示す図である。
解析装置100は、JDBCメソッド132gのログ(DBアクセスログ)をサーバ装置200に採取させ、サーバ装置200からDBアクセスログを取得する。採取するJDBCメソッド132gのログは、関係データベースに対するコネクションがオープンしてからクローズするまでの間のJDBCメソッド132gの処理を示す。解析装置100は、取得したDBアクセスログから動的解析に使用するデータを抽出してDBアクセスログテーブル144(テーブル4)を生成する。DBアクセスログテーブル144は、時刻、SQL文、スタックトレースおよび出力の項目を有する。
時刻は、JDBCメソッド132gが呼び出された時刻である。SQL文は、関係データベースに対して出力したクエリとしてのSQL文である。スタックトレースは、JDBCメソッド132gが呼び出された時点におけるメソッド呼び出しのスタックトレース、すなわち、それまでに階層的に呼び出された複数のメソッドの名称を列挙したものである。メソッド「methodC(int,String)」を経由してJDBCメソッド132gが呼び出された場合、スタックトレースには「methodC(int,String)」の名称が含まれている。メソッド「methodF()」を経由してJDBCメソッド132gが呼び出された場合、スタックトレースには「methodF()」の名称が含まれている。出力は、SQL文に対する応答として関係データベースから取得したデータである。関係データベースへの書き込みを示すSQL文(insert文やupdate文など)に対しては、返り値はnullとなる。
一例として、上記の「methodC(int,String)」の3回の呼び出しと「methodF()」の1回の呼び出しに対応して、JDBCメソッド132gが4回呼び出されたとする。時刻11:22:34に、書き込み値を(50,α,50)とするinsert文が発行されている。時刻11:22:45に、書き込み値を(35,β,0)とするinsert文が発行されている。時刻11:23:00に、書き込み値を(20,γ,0)とするinsert文が発行されている。また、時刻11:28:00に、カラムc1,c2の値を検索するselect文が発行され、{(50,α),(35,β),(20,γ)}という検索結果が取得されている。
図10は、対応候補テーブルの例を示す図である。
解析装置100は、呼び出しログテーブル143とDBアクセスログテーブル144を照合し、メソッドの変数と関係データベースのカラムとの対応関係の候補を抽出し、対応候補テーブル145(テーブル5)を生成する。対応候補テーブル145は、種別、変数名、クラス名、メソッド名、変数型、テーブル名、カラム名および時刻の項目を有する。
種別は、関係データベースに対するアクセスの種別であり、書き込みを示す「Write」または読み出しを示す「Read」である。種別はSQL文から判断できる。insert文やupdate文の種別は「Write」であり、select文の種別は「Read」である。変数名は、呼び出しログテーブル143に記載されたメソッドの引数または返り値としての変数の名称である。クラス名は、メソッドが属するクラスの名称である。メソッド名は、未追跡のメソッドの名称である。変数型は、変数名の項目に登録された変数の型である。テーブル名は、変数に対応する可能性があるカラムの属するデータベーステーブルの名称である。カラム名は、変数に対応する可能性があるカラムの名称である。時刻は、DBアクセスログテーブル144の時刻である。
解析装置100は、次のようにして呼び出しログテーブル143およびDBアクセスログテーブル144から対応候補テーブル145を生成する。解析装置100は、DBアクセスログテーブル144からレコード(DBアクセスレコード)を1つ選択し、選択したDBアクセスレコードに含まれるスタックトレースの中から未追跡のメソッドを検出する。解析装置100は、呼び出しログテーブル143から、検出した未追跡のメソッドをDBアクセスの直前に呼び出しているレコード(呼び出しレコード)を選択する。
選択したDBアクセスレコードに含まれるSQL文がWrite型である場合、解析装置100は、当該SQL文に記載された書き込み値と選択した呼び出しレコードに含まれる引数の値とを比較する。何れかの書き込み値と何れかの引数の値とが一致する場合、解析装置100は、当該書き込み値が書き込まれるカラムと当該引数の値が格納されている変数とを、対応付け候補として対応候補テーブル145に登録する。
選択したDBアクセスレコードに含まれるSQL文がRead型である場合、解析装置100は、選択したDBアクセスレコードに含まれる出力の中の各カラムの値と選択した呼び出しレコードに含まれる返り値とを比較する。返り値の中に要素として何れかのカラムの値が含まれている場合、解析装置100は、当該カラムと返り値を示す変数とを、対応付け候補として対応候補テーブル145に登録する。
対応候補テーブル145のレコードは、選択したDBアクセスレコードと選択した呼び出しレコードから生成できる。なお、呼び出しログテーブル143には引数に対応する変数名は記載されていないが、解析装置100は、静的解析を通じて変数名を取得することができる。また、DBアクセスログテーブル144には書き込み値に対応するカラム名が記載されていないことがあるが、解析装置100は、動的解析の中でJDBCに設定されたクエリテンプレート(プリペアードステートメント)からカラム名を取得できる。
一例として、解析装置100は、図9のDBアクセスログテーブル144から1行目のDBアクセスレコードを選択する。選択したDBアクセスレコードのスタックトレースには、メソッド「methodC(int,String)」の名称が含まれている。すると、解析装置100は、図8の呼び出しログテーブル143から、当該メソッド名を含み、選択したDBアクセスレコードの直前の時刻を含む1行目の呼び出しレコードを選択する。「直前の時刻」は、呼び出しログテーブル143に記載された時刻のうち、DBアクセスレコードの時刻より前であってDBアクセスレコードの時刻に最も近い時刻である。
DBアクセスレコードに含まれるSQL文がWrite型であるため、解析装置100は、呼び出しレコードに含まれる引数の値(50,α)とDBアクセスレコードに含まれる書き込み値(50,α,50)とを比較する。1番目の引数の値が1番目・3番目の書き込み値と一致するため、解析装置100は、変数aとカラムc1の対応関係と、変数aとカラムc3の対応関係を候補とする。また、2番目の引数の値が2番目の書き込み値と一致するため、解析装置100は、変数bとカラムc2の対応関係を候補とする。
また、一例として、解析装置100は、図9のDBアクセスログテーブル144から4行目のDBアクセスレコードを選択する。選択したDBアクセスレコードのスタックトレースには、メソッド「methodF()」の名称が含まれている。すると、解析装置100は、図8の呼び出しログテーブル143から、当該メソッド名を含み、選択したDBアクセスレコードの直前の時刻を含む4行目の呼び出しレコードを選択する。
DBアクセスレコードに含まれるSQL文がRead型であるため、解析装置100は、呼び出しレコードに含まれる返り値{(50,α),(35,β),(20,γ)}とDBアクセスレコードに含まれる出力の値{(50,α),(35,β),(20,γ)}とを比較する。1番目のカラムの値と2番目のカラムの値がメソッドの返り値の要素として含まれているため、解析装置100は、返り値を示す変数とカラムc1の対応関係と、返り値を示す変数とカラムc2の対応関係を候補とする。
図11は、対応テーブルの例を示す図である。
解析装置100は、対応候補テーブル145に記載された各時刻における対応関係の候補を一般化して、全時刻を通じた変数とカラムの対応関係を判定し、対応テーブル146(テーブル6)を生成する。対応テーブル146は、種別、変数名、クラス名、メソッド名、変数型、テーブル名およびカラム名の項目を有する。対応テーブル146が有するこれらの項目は、対応候補テーブル145の同名の項目に相当する。
解析装置100は、対応候補テーブル145から、種別と変数名とクラス名とメソッド名と変数型が同じレコードを抽出し、全ての時刻において共通に出現するテーブル名とカラム名の組を採用し、対応テーブル146に登録する。解析装置100は、一部の時刻においてのみ出現するテーブル名とカラム名の組は採用せずに破棄する。
一例として、解析装置100は、種別と変数名とクラス名とメソッド名と変数型が同じレコードとして、図10の対応候補テーブル145から1行目・3行目・4行目・6行目のレコードを抽出する。抽出したレコードの集合には3つの時刻が存在する。(テーブルT1,カラムc1)は3つの時刻に共通に現れる一方、(テーブルT1,カラムc3)は1つの時刻にのみ現れる。よって、解析装置100は、変数aが(テーブルT1,カラムc1)に対応し、(テーブルT1,カラムc3)には対応しないと判定する。
同様にして、解析装置100は、種別と変数名とクラス名とメソッド名と変数型が同じレコードとして、図10の対応候補テーブル145から2行目・5行目・7行目のレコードを抽出する。抽出したレコードの集合には3つの時刻が存在する。(テーブルT1,カラムc2)は3つの時刻に共通に現れるため、解析装置100は、変数bが(テーブルT1,カラムc2)に対応すると判定する。
図12は、追加影響テーブルの例を示す図である。
解析装置100は、対応テーブル146に登録された変数とカラムの対応関係を辿ることで2つの変数の間の影響関係を抽出し、追加影響テーブル147(テーブル7)を生成する。追加影響テーブル147は、影響テーブル141と同様に、影響元の変数について変数名、クラス名、メソッド名および変数型の項目を有する。また、追加影響テーブル147は、影響先の変数について変数名、クラス名、メソッド名および変数型の項目を有する。追加影響テーブル147は、静的解析では検出できなかったものの動的解析によって検出された影響関係を示している。追加影響テーブル147のレコードを影響テーブル141に加えることで、関係データベースを介した変数間の影響関係が完成する。
解析装置100は、対応テーブル146からWrite型のレコードを1つ選択し、選択したWrite型のレコードのテーブル名とカラム名を抽出する。解析装置100は、抽出したテーブル名とカラム名を含むRead型のレコードを対応テーブル146から検索する。該当するRead型のレコードが検索された場合、解析装置100は、Write型のレコードの変数を影響元とし、Read型のレコードの変数を影響先とする影響関係を追加影響テーブル147に登録する。これは、データベーステーブルの同一のカラムを介して、影響元の変数の値が影響先の変数に伝搬することを意味する。
一例として、解析装置100は、図11の対応テーブル146から1行目のWrite型のレコードを選択し、選択したWrite型のレコードから(テーブルT1,カラムc1)を抽出する。解析装置100は、(テーブルT1,カラムc1)を含む3行目のRead型のレコードを対応テーブル146から検索し、変数aを影響元とし「methodF()」の戻り値を影響先とする影響関係を検出する。
また、解析装置100は、図11の対応テーブル146から2行目のWrite型のレコードを選択し、選択したWrite型のレコードから(テーブルT1,カラムc2)を抽出する。解析装置100は、(テーブルT1,カラムc2)を含む4行目のRead型のレコードを対応テーブル146から検索し、変数bを影響元とし「methodF()」の戻り値を影響先とする影響関係を検出する。
このような追加影響テーブル147のレコードを図6の影響テーブル141に追加することで、次のような影響関係の連鎖が影響テーブル141に表現される。
「methodA()」の変数xは「methodB(int)」の変数aに影響を与え、「methodB(int)」の変数aは「methodC(int,String)」の変数aに影響を与える。また、「methodC(int,String)」の変数aは「methodF()」の戻り値に影響を与える。また、「methodF()」の戻り値は「methodE()」の変数yに影響を与え、「methodE()」の変数yは「methodD()」の変数zに影響を与える。
これらの影響関係を連結すると、「methodA()」の変数xは「methodD()」の変数zに影響を与えることになる。すなわち、「methodA()」の変数xの値が「methodD()」の変数zに伝搬する。このように、関係データベースを介した変数の値の伝搬を表現することが可能となる。
次に、解析装置100の機能について説明する。
図13は、解析装置の機能例を示すブロック図である。
解析装置100は、ソースコード記憶部121、静的解析部122、ログ収集部123、ログ記憶部124、動的解析部125、中間データ記憶部126、解析結果記憶部127および影響範囲出力部128を有する。ソースコード記憶部121、ログ記憶部124、中間データ記憶部126および解析結果記憶部127は、例えば、RAM102またはHDD103に確保した記憶領域を用いて実装される。静的解析部122、ログ収集部123、動的解析部125および影響範囲出力部128は、例えば、CPU101が実行するプログラムモジュールを用いて実装される。
ソースコード記憶部121は、アプリケーションソフトウェアのソースコード131を記憶する。静的解析部122は、ソースコード記憶部121に記憶されたソースコード131に対して静的解析を行い、ソースコード131から検出された変数の値の伝搬を示す影響テーブル141(テーブル1)を生成する。アプリケーションソフトウェアがライブラリを利用してデータベースにアクセスする場合、静的解析部122はデータベースを介した変数の値の伝搬を完全に追跡できないことがある。静的解析部122は、静的解析によって生成した影響テーブル141を解析結果記憶部127に格納する。また、静的解析部122は、解析できなかったメソッドを示す未追跡テーブル142(テーブル2)を生成して中間データ記憶部126に格納する。
ログ収集部123は、未追跡テーブル142に1以上の未追跡メソッドが登録されている場合、動的解析に使用するログを収集する。例えば、ログ収集部123は、アプリケーションプログラムとログ採取のためのエージェントプログラムとをサーバ装置200に配置し、サーバ装置200にアプリケーションプログラムを実行させる。プログラムの中のログ採取位置は、静的解析の結果に基づいて最小限に限定することができる。ログ収集部123は、サーバ装置200が生成したログをサーバ装置200から取得する。ログ収集部123は、ログの内容を示す呼び出しログテーブル143(テーブル3)およびDBアクセスログテーブル144(テーブル4)を生成してログ記憶部124に格納する。
ログ記憶部124は、ログ収集部123が生成した呼び出しログテーブル143およびDBアクセスログテーブル144を記憶する。動的解析部125は、ログ記憶部124に記憶された呼び出しログテーブル143とDBアクセスログテーブル144を使用して動的解析を行い、静的解析で追跡できなかった変数の値の伝搬を補完する。
動的解析部125は、呼び出しログテーブル143とDBアクセスログテーブル144とを比較して、未追跡メソッドの変数とデータベーステーブルのカラムの対応関係の候補を示す対応候補テーブル145(テーブル5)を生成し、中間データ記憶部126に格納する。動的解析部125は、生成した対応候補テーブル145を一般化して対応テーブル146(テーブル6)を生成し、中間データ記憶部126に格納する。動的解析部125は、生成した対応テーブル146を用いて、同じカラムを介して値が伝搬する変数の組を示す追加影響テーブル147(テーブル7)を生成し、中間データ記憶部126に格納する。動的解析部125は、追加影響テーブル147が示す変数の値の伝搬を、解析結果記憶部127に記憶された影響テーブル141に転記する。
中間データ記憶部126は、静的解析部122が生成した未追跡テーブル142を記憶する。また、中間データ記憶部126は、動的解析部125が生成した対応候補テーブル145、対応テーブル146および追加影響テーブル147を記憶する。解析結果記憶部127は、静的解析部122が生成した影響テーブル141を記憶する。影響テーブル141は動的解析部125によって更新されることがある。
影響範囲出力部128は、解析結果記憶部127に記憶された影響テーブル141に基づいて、影響範囲解析の結果を出力する。例えば、影響範囲出力部128は、影響範囲解析の結果をディスプレイ111に表示させる。このとき、影響範囲出力部128は、影響テーブル141に記載されたテキストをディスプレイ111に表示させてもよい。また、影響範囲出力部128は、影響範囲解析の結果を反映した態様でソースコード131をディスプレイ111に表示させてもよい。例えば、影響範囲出力部128は、ユーザが1つの変数を選択すると、選択された変数から影響を受ける他の変数およびメソッドを検索し、検索した他の変数およびメソッドをハイライト表示することが考えられる。
図14は、影響範囲解析の手順例を示すフローチャートである。
(S10)静的解析部122は、ソースコード131を読み込む。
(S11)静的解析部122は、読み込んだソースコード131に対して静的解析を実行する。このとき、静的解析部122は、ソースコード131からメソッドとメソッド内のローカル変数を抽出し、メソッド呼び出しを介した変数の値の伝搬を追跡する。
(S12)静的解析部122は、ステップS11の静的解析によって検出された変数の値の伝搬を影響テーブル141(テーブル1)に記録する。
(S13)静的解析部122は、ステップS11の静的解析において、O/Rマッパーのメソッドなどソースコード131に内容が定義されていないため未追跡となったメソッドがある場合、未追跡メソッドを未追跡テーブル142(テーブル2)に記録する。
(S14)ログ収集部123は、未追跡テーブル142に1以上のレコードが記録されているか判断する。1以上のレコードが記録されている場合はステップS15に処理が進み、1つのレコードも記録されていない場合はステップS21に処理が進む。
(S15)ログ収集部123は、未追跡メソッドの呼び出し元に対して(例えば、未追跡メソッドを呼び出す直前の位置に)、呼び出しログを採取するためのログ採取モジュールを付加する。例えば、ログ収集部123は、バイトコードインジェクションに用いる呼び出しログ採取用のエージェントプログラムを生成する。
(S16)ログ収集部123は、データベースとコネクションを確立しSQL文を発行するJDBCに対して、DBアクセスログを採取するためのログ採取モジュールを付加する。例えば、ログ収集部123は、バイトコードインジェクションに用いるDBアクセスログ採取用のエージェントプログラムを生成する。
(S17)ログ収集部123は、サーバ装置200にアプリケーションプログラムを実行させる。実行させるアプリケーションプログラムは、予めコンパイルされたものでもよいし、解析装置100またはサーバ装置200がソースコード131からコンパイルしたものでもよい。例えば、ログ収集部123は、アプリケーションプログラムおよびエージェントプログラムをサーバ装置200に配置し、ロード時にアプリケーションプログラムを書き換えるオプションを付加した起動コマンドをサーバ装置200に送信する。
(S18)ログ収集部123は、サーバ装置200によるアプリケーションプログラムの実行が終了すると、サーバ装置200から呼び出しログおよびDBアクセスログを読み出す。ログ収集部123は、呼び出しログの内容を呼び出しログテーブル143(テーブル3)に記録する。また、ログ収集部123は、DBアクセスログの内容をDBアクセスログテーブル144(テーブル4)に記録する。
(S19)動的解析部125は、呼び出しログテーブル143およびDBアクセスログテーブル144を用いて動的解析を行い、動的解析の結果を追加影響テーブル147(テーブル7)に記録する。動的解析の手順については後述する。
(S20)動的解析部125は、追加影響テーブル147を影響テーブル141に統合する。すなわち、動的解析部125は、追加影響テーブル147に記録された変数の値の伝搬を影響テーブル141に転記する。これにより、影響テーブル141には、未追跡メソッドを呼び出すまでの区間の伝搬と未追跡メソッドを呼び出して関係データベースにアクセスする区間の伝搬との両方が記録され、両者の連携が表現される。
(S21)影響範囲出力部128は、影響テーブル141に基づいて影響範囲解析の結果を出力する。例えば、影響範囲出力部128は、ある1つの変数から開始して、影響テーブル141に記録された複数のレコードを連続的に辿ることで、当該1つの変数の影響を受ける全ての他の変数や全てのメソッドを網羅的に検索することができる。
図15は、動的解析の手順例を示すフローチャートである。
この動的解析は、前述のステップS19で実行される。
(S30)動的解析部125は、DBアクセスログテーブル144(テーブル4)に記録されているDBアクセスレコードを1つ選択する。
(S31)動的解析部125は、ステップS30で選択したDBアクセスレコードに含まれるスタックトレースの中から、未追跡テーブル142(テーブル2)に記録されている未追跡メソッドの名称を検索する。
(S32)動的解析部125は、スタックトレースから何れかの未追跡メソッドが検出されたか判断する。何れかの未追跡メソッドが検出された場合はステップS33に処理が進み、検出されなかった場合はステップS37に処理が進む。
(S33)動的解析部125は、呼び出しログテーブル143(テーブル3)から、ステップS32の未追跡メソッドの呼び出しを示しており、選択したDBアクセスレコードの直前に生成された呼び出しレコードを選択する。
(S34)動的解析部125は、ステップS30で選択したDBアクセスレコードに含まれるSQL文が、関係データベースを更新するWrite型であるか判断する。insert文やupdate文はWrite型であり、select文はRead型である。SQL文がWrite型である場合はステップS35に処理が進み、SQL文がRead型である場合はステップS36に処理が進む。
(S35)動的解析部125は、選択した呼び出しレコードに含まれる引数の値と選択したDBアクセスレコードに含まれるSQL文の中の書き込み値とを比較し、引数に相当する変数とデータベーステーブルのカラムとの対応関係の候補を生成する。動的解析部125は、生成した対応関係の候補を対応候補テーブル145(テーブル5)に記録する。そして、ステップS37に処理が進む。
(S36)動的解析部125は、選択した呼び出しレコードに含まれる返り値と選択したDBアクセスレコードに含まれるSQL文に対する出力値とを比較し、返り値に相当する変数とデータベーステーブルのカラムとの対応関係の候補を生成する。動的解析部125は、生成した対応関係の候補を対応候補テーブル145に記録する。
(S37)動的解析部125は、ステップS30においてDBアクセスログテーブル144から全てのDBアクセスレコードを選択したか判断する。全てのDBアクセスレコードを選択した場合はステップS38に処理が進み、未選択のDBアクセスレコードがある場合はステップS30に処理が進む。
(S38)動的解析部125は、対応候補テーブル145から全時刻に共通に現れる変数とカラムの対応関係の候補を抽出し、正しい対応関係として採用する。動的解析部125は、採用した対応関係を対応テーブル146(テーブル6)に記録する。
(S39)動的解析部125は、対応テーブル146から、テーブル名およびカラム名が共通するWrite型のレコードとRead型のレコードの組み合わせを検索する。動的解析部125は、検索されたWrite型のレコードとRead型のレコードとを結合して、前者に記載された変数を影響元とし後者に記載された変数を影響先とする伝搬関係を決定する。動的解析部125は、決定した変数の値の伝搬を追加影響テーブル147(テーブル7)に記録する。そして、動的解析が終了する。
第2の実施の形態の情報処理システムによれば、既存ソースコードの修正作業の際に、ある変数の影響を受ける他の変数やメソッドを可視化することができる。よって、意図しない不具合の発生を抑制でき、修正作業を効率化することができる。また、ソースコードの静的解析だけでは追跡できないメソッドを呼び出して関係データベースにアクセスしている場合であっても、動的解析を併用して変数とカラムの対応関係を判定できる。よって、関係データベースを介した変数の値の伝搬を精度よく追跡することができる。
また、静的解析で不足する情報のみを動的解析によって補完すればよいため、動的解析のみで全ての変数の値の伝搬を追跡する場合と比べて、ログを採取する位置を限定することができる。また、ソースコードを用いた静的解析をベースとするため、変数の値の伝搬を網羅的に抽出することが容易となる。よって、影響範囲分析を効率化できる。
[第3の実施の形態]
次に、第3の実施の形態を説明する。第2の実施の形態との違いを中心に説明し、第2の実施の形態と同様の内容については説明を省略することがある。
第2の実施の形態では、図8の呼び出しログを採取する対象メソッド(ログ採取点)は、ソースコードの静的解析によって追跡できなかった未追跡メソッドである。この未追跡メソッドは、関係データベースに対してSQL文を実行するJDBCメソッドにできる限り近いメソッドである。しかし、アプリケーションソフトウェアによっては、複数のデータベーステーブルや複数種類のSQL文が使用されることがあり、ログ採取点の設定が不適切であると、データベーステーブルのカラムとソースコード上の変数との対応付けの精度が低下することがある。そこで、第3の実施の形態では、呼び出しログを採取するログ採取点をSQL文の種類毎に適切に設定できるようにする。
まず、データベーステーブルのカラムとソースコード上の変数とを対応付ける精度に影響を与える状況について説明する。ユーザが作成したソースコードに、複数のデータベーステーブルへのアクセスに使用される共通メソッド(DBアクセッサ)が定義されているとする。DBアクセッサに対してSQL文の種類を示す引数を指定することで、このDB
アクセッサを介して異なるデータベーステーブルにアクセスすることが可能となる。
例えば、データベースには、カラムC1を含むテーブルTaと、カラムC2を含むテーブルTbが含まれているとする。また、ソースコードには、DBアクセッサであるメソッドmcと、変数aを用いてメソッドmcを呼び出すメソッドmaと、変数bを用いてメソッドmcを呼び出すメソッドmbが記載されているとする。メソッドmaはメソッドmcを介してテーブルTaにアクセスしており、変数aはテーブルTaのカラムC1に影響を与える。また、メソッドmbはメソッドmcを介してテーブルTbにアクセスしており、変数bはテーブルTbのカラムC2に影響を与える。
メソッドma,mbよりもメソッドmcの方がJDBCメソッドに近いことから、DBアクセッサであるメソッドmcをログ採取点に設定することが考えられる。しかし、その場合にはメソッドmaからの呼び出しとメソッドmbからの呼び出しとが区別されず、誤った依存関係を判定してしまう可能性がある。例えば、メソッドmaの変数aがテーブルTbのカラムC2に影響を与えるという依存関係や、メソッドmbの変数bがテーブルTaのカラムC1に影響を与えるという依存関係を判定してしまう可能性がある。
一方で、ソースコード上で複数のメソッドから呼び出される共通メソッドを常にログ採取点から除外してしまうと、ログ採取点がJDBCメソッドから遠く離れてしまう可能性がある。ログ採取点とJDBCメソッドが離れていると、ログ採取点における変数の値がJDBCメソッドに伝搬するまでに加工されてしまい、呼び出しログとDBアクセスログを比較してもカラムと変数を対応付けることができない場合がある。
そこで、第3の実施の形態では、複数種類のSQL文それぞれに対して、他の種類のSQL文と区別できる範囲でJDBCメソッドにできる限り近いメソッドをログ採取点として設定する。このために、第3の実施の形態では2段階でログ採取を行う。第1段階ではJDBCメソッドにログ採取モジュールを付加して、データベースアクセス毎にSQL文とスタックトレースを取得する。取得したSQL文とスタックトレースに基づいて、呼び出しログを採取するログ採取点をSQL文の種類毎に決定する。第2段階では決定したログ採取点の呼び出し元とJDBCメソッドにログ採取モジュールを付加して、第2の実施の形態と同様に呼び出しログとDBアクセスログを取得する。このように、第3の実施の形態では動的解析を通じて呼び出しログのログ採取点を決定する。決定したログ採取点は、第2の実施の形態の未追跡メソッドとして取り扱われる。
次に、第3の実施の形態の解析装置100aを説明する。解析装置100aは、第2の実施の形態の解析装置100に代えて使用される。なお、解析装置100aは、図3と同様のハードウェアを用いて実装することができる。
図16は、解析装置の他の機能例を示すブロック図である。
解析装置100aは、ソースコード記憶部121、静的解析部122a、ログ収集部123a、ログ記憶部124、動的解析部125、中間データ記憶部126、解析結果記憶部127、影響範囲出力部128およびログ採取点決定部129を有する。静的解析部122a、ログ収集部123aおよびログ採取点決定部129は、例えば、CPU101が実行するプログラムモジュールを用いて実装される。
静的解析部122aは、第2の実施の形態の静的解析部122と同様に、ソースコード記憶部121に記憶されたソースコードに対して静的解析を行う。ただし、図7の未追跡テーブル142(テーブル2)のメソッドはログ採取点決定部129によって決定されるため、静的解析部122aは未追跡テーブル142を生成しなくてもよい。
ログ収集部123aは、静的解析部122aによる静的解析の後、第1段階として、ログ採取点決定部129によって使用されるログを収集する。第1段階のログには、JDBCメソッドを実行した際のSQL文とスタックトレースが含まれる。また、ログ収集部123aは、ログ採取点決定部129によってログ採取点が決定されると、第2段階として、動的解析部125によって使用されるログを収集する。第2段階のログには、ログ採取点決定部129によって決定されたログ採取点における呼び出しログと、DBアクセスログが含まれる。例えば、ログ収集部123aは、アプリケーションプログラムとログ採取のためのエージェントプログラムとをサーバ装置200に配置し、サーバ装置200にアプリケーションプログラムを実行させる。ログ収集部123aは、サーバ装置200が生成したログをサーバ装置200から取得する。なお、ログ収集部123aは、静的解析部122aによる静的解析の前に第1段階のログ採取を行ってもよい。
ログ採取点決定部129は、ログ収集部123aが収集した第1段階のログを分析して、第2の実施の形態の未追跡メソッドに相当するログ採取点(「DB対応付けログ採取メソッド」などと言うこともできる)を決定する。このとき、ログ採取点決定部129は、ログに含まれるSQL文を複数の種類に分類すると共に、ログに含まれるスタックトレースから複数のメソッドの呼び出し関係を示す呼び出しグラフを生成する。ログ採取点決定部129は、SQL文の種類と呼び出しグラフ上での実行経路との関係を分析し、動的解析に適したメソッドをSQL文の種類毎に選択する。ある種類のSQL文にとって動的解析に適したメソッドとは、他の種類のSQL文と区別することが容易なメソッドのうちJDBCメソッドにできる限り近いメソッドである。
図17は、ラベルテーブルの例を示す図である。
ラベルテーブル148(テーブル8)は、ログ採取点決定部129によって生成されて中間データ記憶部126に記憶される。上記のように、ログ採取点決定部129は第1段階のログに含まれるSQL文を複数種類に分類する。ラベルテーブル148は、SQL文の種類とラベルとを対応付けている。
SQL文の種類は、データベース操作のコマンド種別(INSERTやSELECT)と操作対象テーブルのテーブル名と操作対象カラムのカラム名に基づいて決定される。コマンド種別とテーブル名とカラム名の全てが同じSQL文は同じ種類のSQL文であり、コマンド種別とテーブル名とカラム名の少なくとも1つが異なるSQL文は異なる種類のSQL文である。WHERE句のような条件情報は、SQL文の種類に影響しない。
SQL文の中の一部の文字列が、そのSQL文の種類を示す種類部分として抽出される。種類部分が同じSQL文は同じ種類のSQL文である。例えば、SELECT文の場合、先頭からWHERE句の前までの文字列が種類部分として抽出される。「SELECT C1,C2,C3 FROM T1 WHERE C1=0」というSQL文からは、「SELECT C1,C2,C3 FROM T1」が種類部分として抽出される。また、例えば、INSERT文の場合、先頭からVALUESの前までの文字列が種類部分として抽出される。「INSERT INTO T1(C1,C2,C3) VALUES(10,20,30)」というSQL文からは、「INSERT INTO T1(C1,C2,C3)」が種類部分として抽出される。
SQL文の種類部分に対して、簡潔な文字列としてラベルが付与される。例えば、「SELECT pfa_user_password_id,user_id,change_date,password,delete_flag,insert_date,insert_user,update_date,update_user FROM pfa_user_password」に対してラベルS1が付与される。
図18は、SQL文とスタックトレースの第1の例を示す図である。
ログ収集部123aによって収集される第1段階のログは複数のレコードを含む。これら複数のレコードはログ記憶部124に記憶される。1つのレコードはJDBCメソッドの1回の実行によって生成され、実行されたSQL文とJDBCメソッドが呼び出されるまでに経由したメソッドの列を示すスタックトレースとを含む。
一例として、SQL文151とスタックトレース152を含むレコードがログ記憶部124に記憶される。SQL文151はSELECT文であり、1個のテーブル名と9個のカラム名を含む。SQL文151はラベルS1に分類される。スタックトレース152は、SQL文151を実行する際に呼び出されたメソッドをJDBCメソッドに近い順に列挙したものである。スタックトレース152は、JDBCメソッドと画面制御メソッドの間に4個のメソッドのメソッド名を含んでいる。クラスBaseDaoのメソッドexecuteQuery、クラスPfaUserPasswordDaoのメソッドfindForInfo、クラスAuthBeanのメソッドauthenticate、クラスAuthActionのメソッドauthが記載されている。
図19は、SQL文とスタックトレースの第2の例を示す図である。
更に一例として、SQL文153とスタックトレース154を含むレコードがログ記憶部124に記憶される。SQL文153はSELECT文であり、1個のテーブル名と11個のカラム名を含む。SQL文153はラベルS2に分類される。スタックトレース154は、SQL文153を実行する際に呼び出されたメソッドをJDBCメソッドに近い順に列挙したものである。スタックトレース154は、JDBCメソッドと画面制御メソッドの間に4個のメソッドのメソッド名を含んでいる。クラスBaseDaoのメソッドexecuteQuery、クラスPfmUserDaoのメソッドfindForInfo、クラスUserCheckBeanのメソッドcheckUserRole、クラスAuthActionのメソッドauthが記載されている。
図20は、SQL文とスタックトレースの第3の例を示す図である。
更に一例として、SQL文155とスタックトレース156を含むレコードがログ記憶部124に記憶される。SQL文155はSELECT文であり、SQL文153と同じテーブル名とカラム名を含む。SQL文155はラベルS2に分類される。スタックトレース156は、SQL文155を実行する際に呼び出されたメソッドをJDBCメソッドに近い順に列挙したものである。スタックトレース156は、JDBCメソッドと画面制御メソッドの間に4個のメソッドのメソッド名を含んでいる。クラスBaseDaoのメソッドexecuteQuery、クラスPfmUserDaoのメソッドfindForInfo、クラスUserMasterReferenceBeanのメソッドgetUserInfo、クラスAuthActionのメソッドauthが記載されている。
図21は、呼び出しグラフの生成例を示す図である。
ログ記憶部124に記憶された1つのレコードからは1つの部分グラフを生成することができる。各部分グラフは、スタックトレースに記載されたメソッドを表すノードとメソッド間の呼び出し関係を表すリンクとを含む有向グラフである。各ノードに対しては、SQL文の種類を示すラベルが付加される。複数のレコードに対応する複数の部分グラフを合成することで、全体のメソッド呼び出し関係を示す呼び出しグラフが生成される。
上記のSQL文151とスタックトレース152からは部分グラフ161が生成される。部分グラフ161は、スタックトレース152に記載された4個のメソッドを表す4個のノードを含む。部分グラフ161の各ノードにはラベルS1が付加されている。また、上記のSQL文153とスタックトレース154からは部分グラフ162が生成される。部分グラフ162は、スタックトレース154に記載された4個のメソッドを表す4個のノードを含む。部分グラフ162の各ノードにはラベルS2が付加されている。上記のSQL文155とスタックトレース156からは部分グラフ163が生成される。部分グラフ163は、スタックトレース156に記載された4個のメソッドを表す4個のノードを含む。部分グラフ163の各ノードにはラベルS2が付加されている。
部分グラフ161,162,163を合成することで呼び出しグラフ164が生成される。部分グラフ161,162,163の間で同じメソッドを表すノードは単一のノードに集約される。このとき、集約したノードに付加されるラベルは、集約前のノードに付加されていたラベルの和集合となる。例えば、クラスAuthActionのメソッドauthを表すノードは部分グラフ161,162,163に共通に含まれている。呼び出しグラフ164は、クラスAuthActionのメソッドauthを表す単一のノードを含み、そのノードにはラベルS1,S2が付加される。
生成される呼び出しグラフは、JDBCメソッドを表すノードを終点ノードとしてもつグラフであるが、ツリー構造になるとは限らない。ノード間のリンクは、画面制御メソッドを表すノードからJDBCメソッドを表すノードに向かう方向をもつ。JDBCメソッド側が下流であり、画面制御メソッド側が上流である。
図22は、呼び出しグラフの例を示す図である。
呼び出しグラフ165は、更に他のSQL文およびスタックトレースを用いて呼び出しグラフ164を拡張したものである。呼び出しグラフ165は、ノード165a,165b,165c,165d,165e,165f,165g,165h,165i,165j,165k,165l,165m,165nを含む。
ノード165a,165bは、JDBCメソッドを示す終点ノードから距離1のノードである。ノード165aは、クラスBaseDaoのメソッドexecuteQueryを示し、ラベルS1,S2,S5をもつ。ノード165aの次段は終点ノードである。ノード165bは、クラスBaseDaoのメソッドexecuteUpdateを示し、ラベルS3,S4をもつ。ノード165bの次段は終点ノードである。
ノード165c,165d,165e,165fは、終点ノードから距離2のノードである。ノード165cは、クラスPfmUserPasswordDaoのメソッドfindForInfoを示し、ラベルS1をもつ。ノード165cの次段はノード165aである。ノード165dは、クラスPfmUserDaoのメソッドfindForInfoを示し、ラベルS2をもつ。ノード165dの次段はノード165aである。ノード165eは、クラスTmdTimeRecordDaoのメソッドfindForKeyを示し、ラベルS5をもつ。ノード165eの次段はノード165aである。ノード165fは、クラスBaseDaoのメソッドinsertを示し、ラベルS3,S4をもつ。ノード165fの次段はノード165bである。
ノード165g,165h,165i,165j,165kは、終点ノードから距離3のノードである。ノード165gは、クラスAuthBeanのメソッドauthenticateを示し、ラベルS1をもつ。ノード165gの次段はノード165cである。ノード165hは、クラスUserCheckBeanのメソッドcheckUserRoleを示し、ラベルS2をもつ。ノード165hの次段はノード165dである。ノード165iは、クラスUserMasterReferenceBeanのメソッドgetUserInfoを示し、ラベルS2をもつ。ノード165iの次段はノード165dである。ノード165jは、クラスTimeRecordRegistBeanのメソッドcheckInsertを示し、ラベルS5をもつ。ノード165jの次段はノード165eである。ノード165kは、クラスRestRegistBeanのメソッドinsertを示し、ラベルS3をもつ。ノード165kの次段はノード165fである。
ノード165l,165mは、終点ノードから距離4のノードである。ノード165lは、クラスAuthActionのメソッドauthを示し、ラベルS1,S2をもつ。ノード165lの次段はノード165g,165h,165iである。ノード165mは、クラスTimeRecordRegistBeanのメソッドinsertを示し、ラベルS4,S5をもつ。ノード165mの次段はノード165f,165jである。
ノード165nは、終点ノードから距離5のノードである。ノード165nは、クラスTimeRecordBeanのメソッドrecordPortalTimeを示し、ラベルS3,S4,S5をもつ。ノード165nの次段はノード165m,165kである。呼び出しグラフ165は、画面制御メソッドを示す始点ノードを含む。ノード165l,165nの前段は、例えば、始点ノードである。
次に、上記の呼び出しグラフ165を用いて、SQL文の種類毎に適切なログ採取点を決定する方法、すなわち、ラベル毎に適切なノードを選択する方法を説明する。
図23は、呼び出しグラフの探索例を示す第1の図である。
ログ採取点決定部129は、JDBCメソッドを示す終点ノードから近い順に、単一のラベルをもつノードを探索する。単一のラベルをもつノードが検出された場合、ログ採取点決定部129は、当該ノードがもつラベルに対して当該ノードが示すメソッドを対応付ける。これにより、SQL文の種類1つに対して1つのメソッドがログ採取点として割り当てられる。また、ログ採取点決定部129は、当該ノードから上流(始点ノード方向)に向かって、他のノードから当該ラベルを削除する。原則として、全てのラベルに対してメソッドが対応付けられるまでこれを繰り返す。
上記の呼び出しグラフ165に対しては、まずログ採取点決定部129は、距離1のノード165a,165bを検査する。ノード165a,165bがもつラベルは何れも単一のラベルではない。次にログ採取点決定部129は、距離2のノード165c,165d,165e,165fを検査する。ノード165fがもつラベルは単一のラベルではない一方、ノード165c,165d,165eがもつラベルは単一のラベルである。
ログ採取点決定部129は、ラベルS1に対してノード165cのメソッドを対応付け、ノード165cより上流に位置するノード165g,165lからラベルS1を削除する。また、ログ採取点決定部129は、ラベルS2に対してノード165dのメソッドを対応付け、ノード165dより上流に位置するノード165h,165i,165lからラベルS2を削除する。また、ログ採取点決定部129は、ラベルS5に対してノード165eのメソッドを対応付け、ノード165eより上流に位置するノード165j,165m,165nからラベルS5を削除する。
この時点ではまだラベルS3,S4に対してメソッドが対応付けられていないため、ログ採取点決定部129は呼び出しグラフ165の探索を継続する。
図24は、呼び出しグラフの探索例を示す第2の図である。
次にログ採取点決定部129は、距離3のノード165g,165h,165i,165j,165kを検査する。ノード165g,165h,165i,165jがもつラベルは単一のラベルではない一方、ノード165kがもつラベルは単一のラベルである。ログ採取点決定部129は、ラベルS3に対してノード165kのメソッドを対応付け、ノード165kより上流に位置するノード165nからラベルS3を削除する。
次にログ採取点決定部129は、距離4のノード165l,165mを検査する。ノード165lがもつラベルは単一のラベルではない一方、ノード165mがもつラベルは単一のラベルである。ログ採取点決定部129は、ラベルS4に対してノード165mのメソッドを対応付け、ノード165mより上流に位置するノード165nからラベルS4を削除する。これにより全てのラベルに対してメソッドが対応付けられたため、ログ採取点決定部129は呼び出しグラフ165の探索を終了する。
以上により、異なる種類のSQL文に対して異なるメソッドがログ採取点として割り当てられる。ノード165c,165d,165e,165k,165mのメソッドがログ採取点である。よって、第2段階のログ採取では、ノード165gのメソッドからノード165cのメソッドが呼び出される際の呼び出しログが採取される。また、ノード165h,165iのメソッドからノード165dのメソッドが呼び出される際の呼び出しログが採取される。また、ノード165jのメソッドからノード165eのメソッドが呼び出される際の呼び出しログが採取される。また、ノード165nのメソッドからノード165kのメソッドが呼び出される際の呼び出しログが採取される。また、ノード165nのメソッドからノード165mのメソッドが呼び出される際の呼び出しログが採取される。
ログ採取点決定部129は、上記のラベルとメソッドの対応付けに基づいて、未追跡テーブル142を生成することができる。
次に、解析装置100aの処理手順について説明する。解析装置100aによる影響範囲解析は、図14に示した第2の実施の形態の影響範囲解析のうちステップS13が異なる。解析装置100aは、ステップS13に代えて以下のログ採取点決定を実行する。
図25は、ログ採取点決定の手順例を示すフローチャートである。
(S40)ログ収集部123aは、データベースとコネクションを確立しSQL文を発行するJDBCに対して、DBアクセスログを採取するためのログ採取モジュールを付加する。例えば、ログ収集部123aは、バイトコードインジェクションに用いるDBアクセスログ採取用のエージェントプログラムを生成する。
(S41)ログ収集部123aは、サーバ装置200にアプリケーションプログラムを実行させる。実行させるアプリケーションプログラムは、予めコンパイルされたものでもよいし、解析装置100aまたはサーバ装置200がソースコードからコンパイルしたものでもよい。例えば、ログ収集部123aは、アプリケーションプログラムおよびエージェントプログラムをサーバ装置200に配置し、ロード時にアプリケーションプログラムを書き換えるオプションを付加した起動コマンドをサーバ装置200に送信する。
(S42)ログ収集部123aは、サーバ装置200によるアプリケーションプログラムの実行が終了すると、サーバ装置200からSQL文とスタックトレースを含むログを読み出す。ログ収集部123aは、読み出したログをログ記憶部124に格納する。
(S43)ログ採取点決定部129は、ステップS42のSQL文およびスタックトレースを分析して呼び出しグラフを生成する。呼び出しグラフ生成の詳細は後述する。
(S44)ログ採取点決定部129は、ステップS43の呼び出しグラフを探索してログ採取点を決定する。呼び出しグラフ探索の詳細は後述する。
(S45)ログ採取点決定部129は、ステップS44で決定したログ採取点を未追跡テーブル142(テーブル2)に記録する。
図26は、呼び出しグラフ生成の手順例を示すフローチャートである。
この呼び出しグラフ生成は上記のステップS43で実行される。
(S50)ログ採取点決定部129は、ログのレコードを1つ選択する。
(S51)ログ採取点決定部129は、選択したレコードに含まれるスタックトレースから部分グラフを生成する。部分グラフは、スタックトレースに記載されたメソッドに対応するノードと、それらメソッドの呼び出し順序を示すリンク(エッジ)とを含む。リンクの遷移元は呼び出し元メソッドを表し、リンクの遷移先は呼び出し先メソッドを表す。よって、部分グラフの終点ノードはJDBCメソッドを示す。JDBCメソッドに近付く方向が下流であり、JDBCメソッドから遠ざかる方向が上流である。
(S52)ログ採取点決定部129は、選択したレコードに含まれるSQL文から、SQL文の種類の識別に適した文字列を種類部分として抽出する。抽出する種類部分は、例えば、コマンド種別とテーブル名とカラム名を含み、具体的なカラム値を含まない。
(S53)ログ採取点決定部129は、ステップS52で抽出した種類部分に対応するラベルを定義済みであるか否か判断する。抽出した種類部分がラベルテーブル148に記録されている場合は定義済みであり、ラベルテーブル148に記録されていない場合は未定義である。ラベルが定義済みである場合はステップS55に処理が進み、ラベルが未定義である場合はステップS54に処理が進む。
(S54)ログ採取点決定部129は、ステップS52で抽出した種類部分に対応する新しいラベルを定義してラベルテーブル148(テーブル8)に記録する。
(S55)ログ採取点決定部129は、ステップS51で生成した部分グラフに含まれるノードそれぞれに対して、抽出した種類部分に対応するラベルを付加する。
(S56)ログ採取点決定部129は、ラベルを付加した部分グラフを、現在の呼び出しグラフに統合する。なお、呼び出しグラフの初期状態は空である。よって、1つ目の部分グラフを生成したときは、当該部分グラフが呼び出しグラフとして保持される。2つ目以降の部分グラフを生成したときは、当該部分グラフと現在の呼び出しグラフとの間で共通するノードを検出することで、ノードやラベルやリンクが集約される。
(S57)ログ採取点決定部129は、ステップS50において、ログに含まれる全てのレコードを選択したか判断する。全てのレコードを選択した場合は呼び出しグラフ生成が終了し、未選択のレコードがある場合はステップS50に処理が進む。
図27は、呼び出しグラフ探索の手順例を示すフローチャートである。
この呼び出しグラフ生成は上記のステップS44で実行される。
(S60)ログ採取点決定部129は、距離xを1に設定する。
(S61)ログ採取点決定部129は、JDBCメソッドを示す終点ノード(JDBCノード)からの距離がxであるノードを1つ選択する。
(S62)ログ採取点決定部129は、ステップS61で選択したノード(選択ノード)が単一のラベルをもつか判断する。単一のラベルをもつ場合はステップS63に処理が進み、ラベルをもたないか2以上のラベルをもつ場合はステップS65に処理が進む。
(S63)ログ採取点決定部129は、選択ノードがもつラベルと選択ノードが示すメソッドとを対応付ける。1つのラベルには高々1つのメソッドが対応付けられる。
(S64)ログ採取点決定部129は、選択ノードから上流(JDBCノードから遠ざかる方向)に向かって他のノードを辿り、当該他のノードがもつラベルのうち選択ノードがもつラベルを削除する。ここで言う他のノードは、JDBCノードから選択ノードまでの経路を共有しているノードである。よって、選択ノードより下流(JDBCノードに近付く方向)に存在するノードのラベルは削除されない。また、JDBCノードから選択ノードまでの経路を共有していない異なる枝上のノードのラベルは削除されない。
(S65)ログ採取点決定部129は、JDBCノードからの距離がxであるノードのうち、ステップS61で未選択のノードがあるか判断する。距離がxである未選択のノードがある場合はステップS61に処理が進み、ない場合はステップS66に処理が進む。
(S66)ログ採取点決定部129は、JDBCノードからの距離がxより大きいノードであって、ステップS61で未選択のノードがあるか判断する。未選択のノードがある場合はステップS67に処理が進み、ない場合はステップS68に処理が進む。
(S67)ログ採取点決定部129は、距離xを1だけ増やす。そして、ステップS61に処理が進み、更新後の距離xについてステップS61〜S65が実行される。
(S68)ログ採取点決定部129は、呼び出しグラフに現れるラベルのうちメソッドを対応付けていないラベルがあるか判断する。メソッドを対応付けていないラベルがある場合はステップS69に処理が進み、ない場合は呼び出しグラフ探索が終了する。
(S69)ログ採取点決定部129は、呼び出しグラフに現れるラベルのうちメソッドを対応付けていないラベルの数(残りラベル数)をカウントする。ログ採取点決定部129は、今回のステップS60〜S67の探索によって残りラベル数が減少したか判断する。すなわち、今回のステップS60〜S67の探索の間に、少なくとも1つのラベルに対してメソッドが対応付けられたか判断する。残りラベル数が減少した場合、ステップS60に戻ってステップS60〜S67の探索を再実行する。残りラベル数が減少していない場合、呼び出しグラフ探索が終了する。なお、ステップS60〜S67の探索を繰り返し実行するのは、2以上のラベルをもっていたノードがステップS64のラベル削除によって単一のラベルをもつノードに変化することがあり、ステップS62の条件を満たすノードが増える可能性があるためである。
このようにして、解析装置100aは、決定したログ採取点を示す未追跡テーブル142(テーブル2)を生成することができる。未追跡テーブル142を生成した後の影響範囲解析の手順は第2の実施の形態と同様である。ただし、解析装置100aは、SQL文の種類とメソッドとの対応関係を示す情報を参照して、対応候補テーブル145(テーブル5)から対応テーブル146(テーブル6)を生成する処理(図15のステップS38)の精度を向上させることもできる。以下、そのような変形例について説明する。
図28は、未追跡テーブルの他の例を示す図である。
ログ採取点決定部129は、第2の実施の形態の未追跡テーブル142に代えて、未追跡テーブル142aを生成することもできる。未追跡テーブル142aは、クラス名、メソッド名、呼び出し元およびラベルの項目を含む。クラス名、メソッド名および呼び出し元の項目は、図7の未追跡テーブル142と同様である。未追跡テーブル142aのクラス名とメソッド名は、ログ採取点決定部129が決定したログ採取点のクラス名とメソッド名である。未追跡テーブル142aのラベルは、ログ採取点に対応付けられたラベルであり、ラベルテーブル148に登録されたSQL文の種類を識別する。
次に、図22〜24の呼び出しグラフ165を用いて、図15の動的解析のステップS38の精度に影響を与える状況について説明する。
図29は、対応候補テーブルの他の例を示す図である。
対応候補テーブル145aは、第2の実施の形態の対応候補テーブル145と同様の方法で生成される。図29の対応候補テーブル145aでは、カラムrecord_timeの読み出しに対して、メソッドinsertとメソッドfindForKeyの2つが対応付けられている。これは、ラベルS5に属するSQL文が実行されたときのスタックトレースに、ラベルS5に対応付けられたメソッドfindForKeyに加えて、ラベルS4に対応付けられたメソッドinsertも含まれているためである。
これは、図24において、ラベルS5の実行経路上にラベルS4のログ採取点が存在することからも説明される。このように、第3の実施の形態の呼び出しグラフ探索によっても、ある種類のSQL文の実行経路上に他の種類のSQL文に対応するログ採取点が設定される場合がある。その場合には不要な伝搬関係が出力されてしまうことがある。対応候補テーブル145aでは、カラムrecord_timeの読み出しとメソッドfindForKeyの対応付けが正しく、カラムrecord_timeの読み出しとメソッドinsertの対応付けは誤りである。
そこで、解析装置100aは、対応候補テーブル145aから対応テーブル146を生成する際に、SQL文の種類の情報を用いて、対応候補テーブル145aに登録されたレコードのうち不適切なレコードをフィルタリングする。
図30は、検査テーブルの例を示す図である。
動的解析部125は、ラベルテーブル148から検査テーブル149を生成する。検査テーブル149は、ラベル、種別、テーブル名およびカラム名の項目を含む。ラベルテーブル148の1つのレコードから、検査テーブル149の1つのレコードが生成される。
検査テーブル149のラベルは、ラベルテーブル148のラベルである。検査テーブル149の種別は、ReadまたはWriteであり、ラベルテーブル148のSQL文に含まれるコマンド種別から判断される。SELECT文の種別はReadであり、INSERT文の種別はWriteである。検査テーブル149のテーブル名は、ラベルテーブル148のSQL文に含まれるテーブル名である。検査テーブル149のカラム名は、ラベルテーブル148のSQL文に含まれるカラム名である。
動的解析部125は、未追跡テーブル142aと検査テーブル149を照合して、クラス名とメソッド名に対応する種別とテーブル名とカラム名を判断する。動的解析部125は、この対応関係と整合しない対応候補テーブル145aのレコードを無視する。
未追跡テーブル142aと検査テーブル149からは、例えば、ラベルS4について、クラスTimeRecordRegistBeanのメソッドinsertに対して、テーブルtmd_time_recordのカラムrecord_timeの書き込みが対応付けられる。また、ラベルS5について、クラスTmdTimeRecordDaoのメソッドfindForKeyに対して、テーブルtmd_time_recordのカラムrecord_timeの読み出しが対応付けられる。
対応候補テーブル145aには、種別がWrite、クラス名がTimeRecordRegistBean、メソッド名がinsert、テーブル名がtmd_time_record、カラム名がrecord_timeのレコードが含まれており、このレコードは有効である。また、対応候補テーブル145aには、種別がRead、クラス名がTimeRecordRegistBean、メソッド名がinsert、テーブル名がtmd_time_record、カラム名がrecord_timeのレコードが含まれており、このレコードは有効である。一方、対応候補テーブル145aには、種別がRead、クラス名がTmdTimeRecordDao、メソッド名がfindForKey、テーブル名がtmd_time_record、カラム名がrecord_timeのレコードが含まれており、このレコードは上記と矛盾するため無効である。
このように、未追跡テーブル142aにラベルを付加することで、対応候補テーブル145aから対応テーブル146を生成する際に、対応候補テーブル145aの不適切なレコードをフィルタリングすることができ精度を向上させることができる。
第3の実施の形態の解析装置100aによれば、第2の実施の形態の解析装置100と同様の効果が得られる。更に、解析装置100aによれば、予備的なログ採取を通じて、SQL文の種類とメソッド呼び出しとの関係が分析される。そして、引数や返り値などを含む呼び出しログを採取するログ採取点が、SQL文の種類毎に適切に設定される。よって、複数種類のSQL文の実行に使用される共有メソッドをログ採取点として設定することによる誤った伝搬関係の推定を抑制できる。また、JDBCメソッドから遠いメソッドをログ採取点として設定することによる対応付け失敗を抑制できる。