Adobe
製品
Creative Suiteファミリー
Photoshopファミリー
Acrobatファミリー
Flash Platform
Digital Marketing Suite
Digital Enterprise Platform
Digital Publishing Suite
その他の製品一覧
ソリューション
コンテンツオーサリング
教育
金融機関
デジタルマーケティングソリューション
その他のソリューション
ラーニング サポート ダウンロード 会社情報
ご購入
アドビストア安心のサポート& サービス
アカデミック版のご購入学生、教職員、個人
ライセンスのご購入企業、教育機関、官公庁
販売パートナー
検索
 
情報 サインイン
ようこそ、 カート 注文状況 ユーザー登録
マイアカウント
サインアウト
サインインの目的 お客様のアカウントや体験版ダウンロード、製品の拡張機能、コミュニティエリアへのアクセスなどを管理するため
Adobe
製品 セクション   検索  
ソリューション 会社情報
サポート ラーニング
サインイン ようこそ、 注文状況 ユーザー登録
Qty:
Subtotal
Checkout
Adobe Developer Connection / Flexデベロッパーセンター /

Flex 3 DEEP TIPS #04 「デバッグに役立つTIPS集 パート2」(後編)

著者 篠崎 大地氏

篠崎 大地氏
  • クラスメソッド株式会社

著者 福田 寅成氏

福田 寅成氏

作成日

9 June 2010

ページ ツール

Facebookでシェア
Twitterでツイート
LinkedInでシェア
ブックマーク
印刷

Tags

必要条件

ユーザーレベル

中級

その他の要件

Flex Builder 3又はFlash Builder 4

  • ダウンロード
  • 製品情報

最終完成品

こちらからダウンロードできます。

  • bluehorizon.zip(zip形式/6KB)
  • chartBench.zip(zip形式/7KB)

目次:

はじめに

UIComponent.mx_internal::dispatchEventHookを使って、コンポーネント間のイベントの流れをダンプする

  • 概要
  • 実例

Flash Debugプレーヤーの設定をしてデバッグに役立つ情報を出力させる

  • Flash Playerが実行したメソッドを出力させる
  • Flash Playerが実行した命令を出力させる
  • ログファイルへの出力をバッファさせ、ファイルI/Oの時間を軽減させる

Flex SDKの隠れた便利コマンドを使う

  • SWFにコンパイルされた命令セットも表示できる「swfdump」

Flex SDKの動作を部分的にカスタマイズする

  • Flex framework内のクラスと同名のクラスをプロジェクト内に配置
  • Flex frameworkを自前でビルドする

はじめに

今回は、前回に引き続きデバッグに役立つTIPSをご紹介します。

Flex 3 DEEP TIPS 連載記事一覧

  • Flex 3 DEEP TIPS #01 初期ロード時のフォーカス制御
  • Flex 3 DEEP TIPS #02「Flexアプリケーションに設定できるキーボードショートカット」
  • Flex 3 DEEP TIPS #03 「デバッグに役立つTips集」(前篇)
  • Flex 3 DEEP TIPS #04 「デバッグに役立つTIPS集 パート2」(後編)

Flexコンポーネントが発行するイベントを出力するために

「UIComponent.mx_internal::dispatchEventHook」を使ってみる

 

dispatchEventHookの概要:

前回は「mx_internal」名前空間を使って、Flex Frameworkの内部構造にアクセスする方法を紹介しました。この「dispatchEventHook」も、UIComponent.asで定義されているmx_internal名前空間の静的変数です。(ちなみにFlex SDK 3から追加されました)

「hook」の名前からも推測できるように、この変数には「dispatchEvent」メソッドが呼ばれる直前に実行される関数を定義できます。例えば、Flexコンポーネントがどのようなイベントを発行し、どのように伝わっていくのかを明らかにするため、イベントの内容を出力するメソッドをhookに指定するなどの使用例が考えられます。

「dispatchEventHook」については正式なドキュメントには明記されていないので、UIComponent.asのソースコードで確認しましょう。以下のように定義されています(Flex SDK 3.5.0の場合)。

override public function dispatchEvent(event:Event):Boolean { if (dispatchEventHook != null) dispatchEventHook(event, this); return super.dispatchEvent(event); }

dispatchEventHookに独自の関数を割り当てることで、Flexのビジュアルコンポーネントがイベントを発行する直前に、好きな処理を実行することが出来るようになります。

dispatchEventHookの実際の使用例:

dispatchEventHookにイベントをダンプする単純なメソッドを登録するだけで、コンポーネントが実行時にどんなイベントを発行し、またどのようにイベントが伝播して行くかを、ログとして出力できます。早速やってみましょう。

イベントをダンプするだけの単純なフック用のメソッドを定義し、Flexアプリケーションの初期化のタイミングで、定義したメソッドをdispatchEventHookに指定してみます。

<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:applicationComplete> <![CDATA[ UIComponent.mx_internal::dispatchEventHook = myEventHook; ]]> </mx:applicationComplete> <mx:Script> <![CDATA[ import flash.utils.getTimer; import mx.core.UIComponent; private function myEventHook(e:Event,comp:UIComponent):void { trace(e, getTimer()); } ]]> </mx:Script> <mx:Button label="button"/> </mx:Application>

実行してみましょう。
ボタンをクリックすると、「buttonDown」「updateComplete」などのイベントがログ出力されます。

[Event type="updateComplete" bubbles=false cancelable=false eventPhase=2] 579 [Event type="updateComplete" bubbles=false cancelable=false eventPhase=2] 2855 [Event type="buttonDown" bubbles=false cancelable=false eventPhase=2] 3565

ボタンを操作する際に何が起きているのかを、イベントを通じて把握することが出来ます。

ところで、クリックした場合に出力されるはずの「mouseDown」や「click」などのイベントが、ここでは出力されていない事にお気づきの方もいるでしょう。これは、「mouseDown」や「click」が、Flash Playerが直接発行するイベント(MouseEvent)であるためです。

(※ちなみに、Flash Playerが発行するイベントは、クラスのパッケージ名で判別できます。パッケージ名が”flash.events..”で始まっていれば、そのイベントは*基本的には*Flash Playerが発行します)

dispatchEventHookメソッドでフックできるのは、UIComponentとその派生クラスであるコンポーネントが発行するイベントだけです。注意しましょう。

イベントの流れをログ出力することが何の役に立つのか、今一つイメージが湧かないかも知れないので多少補足します。

例えば、カスタムコンポーネントを作成したものの、挙動がおかしい(重すぎる等)とします。
この時、予期しないイベントのループが起こっていないかの判定のために、カスタムコンポーネントが発行する全てのイベントを、dispatchEventHookを使うことで出力し、判定の材料とすることができます。

また、(複合的な)処理の実行時間の計測をする際にも役に立ちます。例としてチャートについて考えてみましょう。チャートの表示に掛る時間を計測したいとします。

チャートコンポーネントに表示するデータを(dataProvider経由で)設定してから、実際に表示されるまでは、一つのメソッドで完結する訳ではなく、非同期に複数の処理が走るため、実はこれはなかなかやっかいな問題です。どこかに計測ポイントを設定すれば済む問題ではないからです。

コンポーネントへのデータのセット、関連するコンポーネントへのイベントによる通知、…が発生し、最終的に、チャートコンポーネントの描画完了イベント(「updateComplete」イベント)が発生します。
この間に発行される全てのイベントをダンプすることで、処理の開始から終了までに実際に掛った時間を洗い出すことが可能になります。

ところで、dispatchEventHookに適用できるメソッドを含むライブラリ(.swc)を用意しました。
最後のダウンロードの項をご参照下さい。

  • bluehorizon.zip -> ライブラリ
  • chartBench.zip -> ライブラリの使用例

Flash Player(デバッグ版)の設定をしてデバッグに役立つ情報を出力させる

Flash Playerのデバッグ版を利用することで、実行時にさまざまな情報を出力することができます。
通常Flash Builderをインストールする際に、デバッグ版のPlayerもインストールされますが、下記のURLから個別に入手してインストールすることも可能です。
http://www.adobe.com/support/flashplayer/downloads.html

リリース版のFlash Player同様、Internet Explorer用とそれ以外のブラウザ用の2種類がありますので、適切な方(あるいは両方)をダウンロード、インストールして下さい。
デバッグ版のFlash Playerの挙動を設定するには、「mm.cfg」というファイルを作成する必要があります。詳細については以下のURLで解説されている通りですが、ここでは設定方法を抜粋して紹介します。

「デバッガ版の Flash Player の構成」 (Adobe Flex 3 ヘルプ)
http://livedocs.adobe.com/flex/3_jp/html/help.html?content=logging_04.html

始めに、以下の場所にmm.cfgを作成します。

Windows 2000 / XP C:¥Documents and Settings¥<ユーザ名>
Windows Vista C:¥Users¥<ユーザ名>
Macintosh OS X /Users/<ユーザ名>
又は
/Library/Application Support/Macromedia

それでは、mm.cfgの設定例を見ていきます。

trace関数の呼び出し結果をログファイルに出力させる

mm.cfgに以下を記述します

ErrorReportingEnable=1 TraceOutputFileEnable=1

trace関数の呼び出しを含むSWFを実行すると、trace関数に指定した文字列が「flashlog.txt」という名前のログファイルに出力されます。出力先は以下の表の通りです。

ログファイルの出力先:

Windows 95/98/ME/2000/XP C:¥Documents and Settings¥<ユーザ名>¥Application Data¥Macromedia¥Flash Player¥Logs
Windows Vista C:¥Users¥<ユーザ名>¥AppData¥Roaming¥Macromedia¥Flash Player¥Logs
Macintosh OS X /Users/username/Library/Preferences/Macromedia/Flash Player/Logs/

オブジェクトの構造を出力したい時は、Flex SDKのmx.utils.ObjectUtil.toString()を呼ぶことで詳細な出力が得られます。

例:

import mx.utils.ObjectUtil; var complexStructure:Object = {/* … */ } trace(ObjectUtil.toString(complexStructure));

また、flash.utils.getTimer()を呼ぶことで、Flash Playerが実行を開始した時点からのタイムスタンプが得られます。

例: 簡単なベンチマークを取る:

import flash.utils.getTimer; const timestamp:int = getTimer(); longlongOperation(); trace(getTimer() - timestamp); // 処理にかかった時間を出力 (ミリ秒)

Flash Playerが実行したメソッドを出力させる

mm.cfgに以下のように記述してください。

AS3Trace=1

Flash Playerが実行した命令を出力させる

 

AS3Verbose=1

Flash Virtual Machineが実行した命令が出力されます。
膨大なログが吐かれ、ログ出力の処理時間が増大するため、大きなSWFファイルを実行するとあたかもFlash Builderがフリーズしたかのようになる場合があります。注意して使ってください。

ログファイルへの出力をバッファさせ、ファイルI/Oの時間を軽減させる

 

TraceOutputBuffered = 1

Flash Playerの再描画領域を可視化する

見落としがちですが、デバッグに役立つ機能です。
デバッグ版 Flash Playerの実行時に、右クリックしてコンテキストメニューから「再描画領域を表示」を選択することで、再描画領域が赤い枠で表示されます。

この設定を行うことで、不要な、あるいは不自然な領域での再描画が発生していないか、実装者以外も確認が可能ですので、テストの際などに細かく確認することをお勧めします。
作成したカスタムコンポーネントの動作が重い場合などに、無駄な再描画をしていないかについては案外判別しにくいので、再描画領域を表示するだけでも思わぬ発見に繋がることがあります。

/content/dotcom/jp/devnet/flex/articles/deep_tips_for_debug_part2/jcr:content/articlecontentAdobe/image/file

Flex SDKの隠れた便利コマンドを使う

SWFにコンパイルされた命令セットも表示できる「swfdump」

swfdumpとは

「swfdump」は、SWFファイルの詳細な情報を出力する、コマンドラインツールです。
SWFファイルの構造をXMLで出力する機能、SWFファイル内にコンパイルインされたバイトコードの命令セットを、アセンブリ形式で表示する機能などがあります。

「swfdump」は、Flex SDK 3系の配布物の中には含まれていませんでしたが、Flex SDK 4(4.0.0.14159で確認)には含まれていますので、Flex SDK 4をインストールし、そのSDKディレクトリの「bin」ディレクトリにパスを通すことで使用できます。
(Flex SDK 3系では、SDKソースコード一式をAdobeのリポジトリから取得してビルドすることによって、swfdumpを生成できました)

swfdumpの使い方

コマンドライン引数に、情報をダンプしたいSWFファイル、又はSWFファイルのURLを指定することで、SWFの情報がXMLで出力されます。
コマンドラインオプションを組み合わせることで、出力される項目を削除・追加できます。例えば、「-abc」オプションを付けることで、SWFファイル内のバイトコードをディスアセンブルするよう指定できます。

swfdumpに指定できるオプション:

C:¥devel¥flex¥sdk¥4.00.145159> swfdump Usage: java tools.SwfxPrinter [-encode] [-asm] [-abc] [-noactions] [-showdebugsource] [-showoffset] [-noglyphs] [-external] [-save file.swf] [-nofunctions] [-out file.swfx] file1.swf ...

SWFをコンパイルするのに使ったFlex SDKのバージョン、フレームレート、指定されたメタデータなどを確認することが可能です。また出力形式がパースし易いXMLですので、作成(・デプロイ)したFlexアプリケーションが意図した通りかどうかの検証を、外部スクリプト等との組み合わせで自動化する、などの利用方法が考えられます

少々余談になりますが、「-abc」オプションによるディスアセンブリの出力について、筆者は、開発したFlexアプリケーションで問題があった際の原因究明の際に利用し、助かった経験があります。

あるFlexアプリケーションをデバッグビルドした際には動作に問題がなかったものの、(全く同じソースコードに対して)リリースビルドを行うと、実行時にエラーが発生してしまう、ということがありました。
それで、両方のビルドで生成されたSWFに対し、それぞれ「swfdump -abc」を実行して、生成された命令セットの差分を比較しました。

その結果、実行時エラーとなったメソッドで、ビルド間で命令セットの差異が生じていることが確認でき、問題の原因が特定できました。(結局、問題の原因として特定したメソッド内での実装方法を調整することで解決)

参考までに、swfdumpによる出力例を以下に示します。

swfdumpによる出力例:

<!-- Parsing swf file://C:/hello.swf --> <!-- ?xml version="1.0" encoding="UTF-8"? --> <swf xmlns='http://macromedia/2003/swfx' version='9' framerate='24' size='10000x7500' compressed='true' > <!-- framecount=1 length=858 --> <FileAttributes hasMetadata='true' actionScript3='true' suppressCrossDomainCaching='false' swfRelativeUrls='false' useNetwork='true'/> <Metadata> <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'><rdf:Description rdf:about='' xmlns:dc='http://purl.org/dc/elements/1.1'><dc:format>application/x-shockwave-flash</dc:format><dc:title>Adobe Flex 3 Application</dc:title><dc:description>http://www.adobe.com/products/flex</dc:description><dc:publisher>unknown</dc:publisher><dc:creator>unknown</dc:creator><dc:language>EN</dc:language><dc:date>2010/05/20</dc:date></rdf:Description></rdf:RDF> </Metadata> <ScriptLimits scriptRecursionLimit='1000' scriptTimeLimit='60'/> <SetBackgroundColor color='#869CA7'/> <ProductInfo product='Adobe Flex' edition='' version='3.5' build='12683' compileDate='10/05/20 13:15'/> <FrameLabel label='Hello'/> <DoABC2 name='frame1'> </DoABC2> <SymbolClass> <Symbol idref='0' className='Hello' /> </SymbolClass> <ShowFrame/> </swf>

Flex SDKの動作を部分的にカスタマイズする

例えば、カスタムコンポーネントを開発する際などに、

  • Flex SDKの標準コンポーネントに少し手を加えて様子を見てみたい
  • trace呼び出しを追加して出力を見てみたい

といった場合があると思います。そのための手順を紹介します。

Flex Framework内のクラスと同名のクラスをプロジェクト内に配置する

比較的簡単な手順で試してみることができる方法です。
本格的に行うには、Flex SDKの公開リポジトリからソースコード一式を手に入れてリビルドし、作成したswcをプロジェクトで使用します(手順は後述します)。

例として、UIComponent.asのカスタマイズをしてみましょう。

  1. プロジェクト内に、mx.coreというフォルダーを作成(Flex FrameworkのUIComponentクラスのパッケージと同様のフォルダー構造にする)。
  2. UIComponent.asというファイルを作成
  3. Flex FrameworkのUIComponent.asの内容を、上のファイルにコピー&ペースト
  4. UIComponent.asが参照(include)しているファイルがあるので、プロジェクト内にコピー。
    (mx.coreVersion.as や mx.styles.* 等)
  5. ビルドして実行。試しに、UIComponent.asのコメントアウトされているtrace文を有効にしてみると分かり易いでしょう。
    Flex FrameworkのUIComponentではなく、プロジェクトに配置したUIComponentが使用されていることが確認できるはずです。

UIComponentカスタマイズ時のプロジェクト構成:

/content/dotcom/jp/devnet/flex/articles/deep_tips_for_debug_part2/jcr:content/articlecontentAdobe/image_0/file

Flex Frameworkをリビルドする

上記をより本格的に行うためには、Flex SDKをリビルドしてライブラリ(swcファイル)を作成し、プロジェクトのリンク設定で、ビルドしたライブラリを指定します。
Flex SDKのクラスファイルをカスタマイズする場合は、都度ライブラリをビルドします。

Flex SDKをリポジトリから入手する

Flex SDKのソースリポジトリは、以下になります。(Subversionで運用されています)

http://opensource.adobe.com/svn/opensource/flex/sdk/

まずは、Subversionのクライアントをインストールし、リポジトリからソースコードをチェックアウトしましょう。Windows環境であれば、TortoiseSVNやCygwinをインストールするのが手軽です。

では、早速Flex SDK 3系の最新版が開発されているブランチ「branches/3.x」を取得してみます。
Cygwinでの例になります。

C:¥> mkdir c:¥devel¥flex¥sdk¥branches C:¥> cd C:¥devel¥flex¥sdk¥braches C:¥devel¥flex¥sdk¥branches> svn co http://opensource.adobe.com/svn/opensoruce/flex/sdk/branches/3.x/ ※注 実際には一行です。改行は入力しないで下さい

ソースコードに加えてFlash Player本体等も含まれるため、ファイルサイズの合計は410M程と大きいです。全てチェックアウトするまでには10分程度かかるのではないでしょうか。

Flex SDKのビルドには「Apache Ant」と「Java 開発キット(JDK)」が必要ですので、事前にインストールしてください。ビルド自体は簡単で、SDKのトップレベルのディレクトリに移動して、「ant」を実行するだけです。

C:¥devel¥flex¥sdk¥branches> cd 3.x C:¥devel¥flex¥sdk¥branches¥3.x> ant

これで一式ビルドされます。あとは、作成されたライブラリファイル(*.swc)を、プロジェクトのリンク設定に指定すれば完了です。

参考までに、テストプロジェクトを作成して標準のリンク設定を変更し、ビルドしたライブラリファイルを参照させた時のスクリーンショットです。

/content/dotcom/jp/devnet/flex/articles/deep_tips_for_debug_part2/jcr:content/articlecontentAdobe/image_1/file

加えて、Flex Frameworkのクラスに対してブレークポイントを設定できるように、Flex Frameworkのトップレベルのフォルダーへの参照(例: 「mx」)もプロジェクトに加えると更に便利でしょう。

Eclipseでフォルダーへのリンクを作成するには、メニューから[File]-[New]-[Folder]と選択し、表示されたダイアログの左下にある「Advanced >>」ボタンをクリック、リンク先のディレクトリをダイアログで選択することにより行えます。

/content/dotcom/jp/devnet/flex/articles/deep_tips_for_debug_part2/jcr:content/articlecontentAdobe/image_2/file

普段、あまり具体的に扱うことのない基底クラス、例えばUIComponentやListBaseの構成や実行時の振る舞いを理解するために、これらのクラスの小規模なカスタマイズを加えて動かしてみるのは有効です。是非お試し下さい。

おわりに

デバッグに役立つTIPSを紹介してきましたが、いかがでしたでしょうか。
Flexアプリケーション開発の一助となれば幸いです。

ささやかながら、冒頭で紹介したdispatchEventHookを登録してイベントフローをダンプするメソッドをライブラリ化しました。 ライブラリを使ってイベントフローをダンプするには、プロジェクトの「libs」ディレクトリに「bluehorizon.swc」をコピーし、コンパイラ設定に「-includes+=jp.classmethod.bluehorizon.debug.EventDumper」を追加して下さい。発生したイベントをインデントしてtrace出力します。

製品

  • Creative Suiteファミリー
  • Photoshopファミリー
  • Acrobatファミリー
  • Flashプラットフォーム
  • Digital Marketing Suite
  • Digital Enterprise Suite
  • Digital Publishing Suite
  • モバイルアプリ

ソリューション

  • カスタマーエクスペリエンスマネジメント
  • コンテンツオーサリング
  • デジタルマーケティング

業種別ソリューション

  • 教育
  • 金融機関

サポート

  • ヘルプ&サポート
  • 注文と返品
  • ダウンロードに関するヘルプ
  • ユーザー登録に関するヘルプ

ラーニング

  • ADC: Adobe Developer Center
  • Adobe TV
  • Design Magazine
  • Photoshop Magazine
  • Focus In

ご購入方法

  • アドビストア
  • アカデミック版のご購入
  • ライセンスのご購入

ダウンロード

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

会社情報

  • プレスルーム
  • パートナープログラム
  • 企業の社会的責任(英語)
  • 採用情報
  • 投資家の皆様へ(英語)
  • イベント&セミナー
  • Legal(英語)
  • お問い合わせ
国・地域および言語の選択 日本(変更)
国・地域および言語の選択 閉じる

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • España
  • France
  • Deutschland
  • Hrvatska
  • Ireland
  • Israel - English
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • Magyarország
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Österreich - Deutsch
  • Polska
  • Portugal
  • România
  • Россия
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Slovenija
  • Slovensko
  • Srbija
  • Suomi
  • Sverige
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • Pacific - English
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

当Webサイトをご利用のお客様は、利用条件およびプライバシーポリシー(2011年9月30日更新)にご同意いただいたものとみなされます。

Reviewed by TRUSTe: site privacy statement