コンテンツ・メディア第1事業部の荒木です。ピクトリンクというアプリのAndroid版を作っています。今回は、Google Tag Manager(以下、GTM)でAndroidアプリのABテストを効果的に行うためにウェブテストの目的を設定します。ちなみに今回の記事の内容は、Androidアプリに限らずiOSアプリでも使えます。

GTMによるモバイルアプリのABテスト開始方法については、前回の記事(Google Tag Manager でAndroidアプリのABテスト -ABの出し分け-)を参照してください。

設定の概要

ウェブテストの目的は、各パターン(Aパターン、Bパターン)の優劣判定に使われます。GTMは、ウェブテストの目的を基準にして各パターンの優劣を判定します。GTMの「Google アナリティクスのウェブテスト」変数の編集画面から目的を設定することができます。

ウェブテストの目的

デフォルトでは、スクリーン数、セッションの長さ、例外数、クラッシュ数の四つから選ぶことができます。たとえば、スクリーン数をウェブテストの目的に設定していると、Google Analytics(以下、GA)で送信したスクリーン数が多いパターンが優秀と判定され、クラッシュ数を目的に設定していると、クラッシュ数が少ないパターンが優秀と判断されます。

GAの目標を作成する

さて、ここで特定ボタンのクリックイベントが多いパターンを優秀と判定したい場合を考えてみましょう。カスタムの目的を設定するには、GAの目標を利用します。GAにログインし、「アナリティクス設定」タブの「目標」を選択してください。このとき、アカウント・プロパティ・ビューがGTMのウェブテストと連携していることを確認してください。

GAの目標を選択

目標の設定画面に遷移したら、「+新しい目標」ボタンから目標の作成を開始してください。目標作成は「① 目標設定」「② 目標の説明」「③ 目標の詳細」の3ステップで実施します。

① 目標設定

「テンプレート」と「カスタム」から選びます。テンプレートは、プロパティ設定で指定されている業種で一般的に目標に設定されるものの候補を表示してくれるので、これから何を目標とすべきかわからないときに参考にしてください。今回は特定ボタンのクリックという目標がすでに決まっているので、「カスタム」を選択します。

② 目標の説明

ここでは、目標の名前とタイプを設定します。タイプとは目標の達成基準に関わるもので、全4種あります。以下は、各タイプの目標達成基準です。

  • 到達ページ:特定スクリーンへ到達したか
  • 滞在時間:滞在時間が設定した時間より長いか
  • ページビュー数 または スクリーンビュー数:1セッションあたりのPV数またはスクリーン数が設定した数より多いか
  • イベント:特定イベントが送信されたか

今回は、ボタンのクリックイベントを目標としたいので、「イベント」を選択します。

目標の説明

③ 目標の詳細

ここでは、 ②で選択した目標タイプごとの詳細設定を行います。今回は、イベントの目標詳細を設定します。イベントの詳細設定では、GAイベントのカテゴリ、アクション、ラベル、値についてそれぞれ条件を設定することができます。カテゴリ、アクション、ラベルは「等しい」「先頭が一致」「正規表現」で一致条件を設定します。値については、「超」「完全一致」「未満」で条件を設定できます。ここで設定した条件が全て満たされた場合に、目標達成となります。なお、空欄の条件は無視されます。

目標の詳細

GAの目標を目的に設定する

GAの目標作成が完了したら、GTMの設定に戻ります。「Google アナリティクスのウェブテスト」変数の編集画面で設定できるウェブテストの目的に、先ほど作成したGAの目標「特定のボタンをタップ」が追加されています。これを選択すれば、ボタンのクリック率が良いパターンが優秀と判定されるようになります。

GAの目標をテスト目的に

テスト結果の確認

テスト結果の確認は、GAで行います。GA左サイドメニューの「行動」→「ウェブテスト」から、ウェブテストの進捗や結果が確認できます。ウェブテストの目的で設定した基準の達成率(コンバージョン率)を元に、各パターンの優劣が判定されます。GTMの設定によっては、テスト終了時に成果の高いパターンに自動で固定したり、テスト中に徐々に成果の高いパターンに移行していくということが可能です。

ウェブテストの結果

おわりに

ウェブテストの目的を適切に設定することで、ユーザーの動向にリアルタイムに追従して、より適切な画面を出せるようになります。みなさんもウェブテストの目的を設定して、よりユーザーに楽しんでもらえるようなアプリを作りましょう!

以上です。



Hello world! コンテンツ・メディア第1事業部のjyukutyoこと阪田です。

5/21(土)に開催されたJJUG CCC 2016 Springにて登壇しました。「Seasar2で作った俺たちのサービスの今」というセッションです。
登壇のいきさつはこちらに書いています。

JJUG CCC 2016 Springで登壇します!

そして、スライドはこちらです。

私の感想/思い

技術の解説ではなく実際のサービスの設計判断や詳細を話すというのは、自分のすべてをさらけだす感じがします。私のこのセッションが、弊社フリューの技術レベルの基準になるとも言えます。
もちろん私は天才プログラマーではなく、知らない知識や誤った判断などがあります。それでもこうして発表することで、そうした部分を教えていただき、改善へのアドバイスをいただくことができました。大切なことは、そうした知識を得て私自身の能力が向上すること、そしてサービスがよくなることですから。

私の部署のアプリケーションは、利用者数も1,000万人を超え、決して小さくないサービスです。精鋭エンジニア集団というよりは、向上心はあるけれども、私を始めある種普通(定義が難しいですが)のエンジニアが集まったチームです。そんな状況でも四苦八苦しながらこのレベルのサービスを運用開発できるということも伝えたかったことです。

私の思い

Twitterやブログで感想もたくさんいただくことができました。Twitterではハッシュタクグ「#ccc_gh6」に主に集まっています。「理想ではなく現実解で進んでいること、メンバーのことを考えながら進んでいることに共感できた」という言葉を多くいただきました。私が伝えたかったのは、技術的方法論ではなく、ベストな正解などはなく、自分の置かれた背景、コンテキストに合わせて、よりベターな方法を探りながら進んでいくしかなく、多くの誤りをしながらもそこからフィードバックを得て誤りを直し進めばいいということでした。

エンジニアは論理性や一貫性の能力が高いですから、システムやアプリケーションの今の状況、つまりスナップショットを見て、「ダメ!」という判断を下してそれで終わらせることがあります。でもシステムやサービスには時間軸があります。時間の経過とともに変化していくものです。もちろん置かれている状況によっては、契約や納品など簡単には適用できない現場もあるかとは思います。ただ、そんな中でも時間軸があり、「終わっている!」というときでも今から変化させていくことができます。

CCC自体の感想

私が聴講した他のセッションについては、別のエントリで書きたいと思います。ここではCCCというイベント全体についての感想を書きます。

今回のCCCは登録者数1,200名以上、実際の参加者も800名以上とのことでした。私も関西Javaエンジニアの会(関ジャバ)の会長という立場ではありますが、スケールが違いすぎます。CCC1回の会場費も200万円!JJUG会長である鈴木さんのスライドに記載があります。

これだけのイベントを運営するJJUG幹事、スタッフの方はとても大変だと想像します。これを年2回開催されていることに頭が下がります。

関西から参加されている方も10名以上はおられました。私が知っている方だけでその人数ですので、実際はもっと多いでしょう。次のCCCは秋頃に開催されますので、ぜひみなさんにも参加をお勧めいたします!



初めまして、フリュー佐藤、こと、ジョンです。 安心してください、普通の日本人です。

普段は「ピクトリンク」のサイトの開発、運用しており、サーバサイドの開発を行っております。

今回はSPAJAM2016 大阪予選に参加したことを書きたいと思います

SPAJAM2016とは

http://spajam.jp/

スマートフォンアプリジャム2016、2日間でスマートフォンアプリを開発するハッカソンイベントです。

spajam6

全国で予選があり、本戦が温泉地で行われます。本戦には、各予選での最優秀賞の9組、各予選の優秀賞の中から2組、学生枠で1組が本戦に参加することができます。

SPAということで温泉に浸かり、頭をリフレッシュしながらの開発です。 素晴らしいですね。

本戦で優勝するとシリコンバレーツアーがプレゼントされます。 素晴らしいですね。

SPAJAMに参加する前準備

チームはプログラマ3人、デザイナー1人、プランナー1人という構成でした。 プログラマは業務で画像処理をメインにやっていた2人と、僕でした。

つまり、圧倒的なスマートフォンアプリ開発者不足。逆に言えば、これからどうやって開発していこうかと考える幅がありました。

……いや、正直言ってそんな暇はありませんでした。出場が決まってから当日までは2週間ほどです。

とりあえず手持ちの環境で、かつ、ネイティブアプリ作成ができそうなものということでAndroidのネイティブ開発にしました。Androidの開発は弊社でも行われていたため、その人達に教えてもらいながら勉強をしました。

全員ハッカソン自体にも出たことがないので、半日での模擬ハッカソンをしてみました。

ハッカソンの結果、様々な課題が見えてきました。

僕の方から、開発環境として以下のものを勧めてみました。

  • バージョン管理システム:Git

ブランチの切り替えが早い。また、githubを使うとレポジトリが無料で使えるのでcodeの共有も簡単。

  • 統合開発環境(IDE):Android Studio

Googleが提供しているIntelliJがベースとなっているIDE。弊社Android開発でも使用しているため、ノウハウはある。

  • Slack

無料で使えるコミュニケーションツール。チャットも使え、ファイルの共有もできる。また、Mac、Windows関係がなく使うことができる。

しかし、他のメンバーは、他の開発環境(svnやVisual Studioなど)を使っており、馴染みがなく、僕もきちんと説明している暇もなく、あまつさえAndroidに関しては僕も詳しくないので、お世辞にもスマートな開発ではありませんでした。

ハッカソンの結果を踏まえ、2週間ほどで得た付け焼き刃立派な知識の中で、結局このチームで何ができるのか、できないのかを考えました。

結果、ツールは触りながら覚え、それにプラスして、チームでのカラーを出せるように、画像処理を使ったアプリが開発出来るように環境を整えることで、本番を迎えようと決めました。

模擬ハッカソンはやっておいて本当に良かったです。本番で起こりえそうな問題(proxy、ソースコードの競合などの技術的問題から、プレゼンでの発表形式、画像の共有のしかたなどのハッカソンの進め方まで)について身をもって体感できたからです。

大きなディスプレイとmac miniをキャリーカーに詰めて出発です。(僕だけ

SPAJAM当日

予選会場はYahoo!JAPAN大阪でした。27階という高層。

spajam風景1

高所恐怖症の人はまずそれとの勝負(僕だけ

今回のテーマは、「おでかけを楽しむ」でした。

アイデアソンでは、たくさんのアイデアが出てきましたが、チーム内ではこれだというアイデアは出てきませんでした。15時まで考えつづけましたが結局はいいアイデアが出ず、当初の予定である画像処理を使ったアプリを考えるようにしました。

役割分担は以下です。

  • 僕: UIまわりの組み立て
  • プログラマ他二人: 画像処理部分を作成
  • プランナー: アプリの仕様、その見せ方
  • デザイナー: 発表資料やアプリに必要な画像の作成

UI周りについてもいろいろ考えたりしていました。

spajam2

時間がないうちにどれだけ完成に近づけるか、プレゼンで発表される部分を意識して作成をしていきました。

spajam7

最終的には各自、自分の担当範囲だけではなく、今何が足りていないのか、時間が決まっているなかで、何ができて、何ができないのかを考え行動していけていました。

成果物について

今回作成したアプリは以下です。

パシャ男

「お出かけを楽しむ」ため、お出かけ中にライブでアルバムを埋めていくアプリとなっています。

spajam4

レイアウトを決めて(プレゼンテーションの時は全部同じレイアウトでした。

Screenshot_2016-05-15-18-07-54

カメラアイコンをタップすると写真がとれます。また、動画を撮影することができます。

Screenshot_2016-05-15-18-08-04

しかし、パシャ男の本気はこれだけではありません。写真を取る際に通行人を消すことができるのです。

これがプレゼンテーションでは大きく反響を得られました。

結果

大阪予選計12チームがあり、僕達のチーム以外にも、他のチームのアプリもとても魅力的なものが多く、SPAJAMのレベルの高さを感じました。また、学生のスキルの高さにも驚かされました。

しかし、そんな中、僕達のチームはプレゼンテーションを完璧にこなすことができ、結果

最優秀賞

をいただくことができました。

OLYMPUS DIGITAL CAMERA

総評としては

  • 画像処理などの技術力が光っていた
  • アプリのUI部分で完成度が高かった
  • アイデアについては他の優秀賞とも比べると少し弱かった

とのことです。これを次の本戦で活かしていきたいです。

まとめ

ここまでで説明させていただいた通り、アプリ開発をやったことのないメンバでもアプリを開発することができました。また、アプリ開発においては秀でた知識は無いですが、それを他の知識でカバーして、最優秀賞をいただくことができました。

本戦は、7月2日(土)〜7月4日(月)です。それまで、今回受けた刺激や、面白いと思ったアイデアをどうやれば実現できるのかという部分まで落とし込んで、実装力を上げて行きたいと思います。

この記事を読んだ方で興味がある方、まだ、予選の応募ができる箇所がありますのでぜひ申し込んでみてください!



コンテンツ・メディア第1事業部の荒木です。 今回は、Google Tag Manager を利用してAndroidアプリでABテストをするために、AパターンとBパターンをアプリで出し分ける方法を紹介したいと思います。

Google Tag Manager とは

Google Tag Manager(以下、GTM)は、タグと呼ばれるウェブサイトに埋め込む解析用のコードを管理するためのツールです。たとえば、Google Analytics用の共通タグを各ページに埋め込んでおけば、イベント名などの設定を全てウェブ上で実施できるといったメリットがあります。

GTMでABテストをするメリット

Google AnalyticsとアプリのプログラムだけでABテストの仕組みを作ることは可能です。しかし、GTMによるABテストには、少なくとも以下のメリットがあります。

  • テスト結果の解析を自動で行って、成果の高いパターンに移行してくれる
  • ABテスト用のGAイベント送信が不要である
  • ABテストの開始条件(アプリバージョンや、日時)をプログラムに書かなくて良い

GTM自体のメリットと同様、テストの設定とプログラムを独立できるというのが良い点です。

コンテナの作成

実際にタグの管理を行うために作成するものがコンテナです。GTMではコンテナの設定によって、タグを管理します。 初めてGTMにログインしたときは、アカウントとコンテナを一つずつ作成することになります。今回は、コンテナの使用場所として「Android」を選択します。

アカウントとコンテナの作成

Google Analytics と連携する

コンテナと Google Analytics (以下、GA)を連携させることで、ABテストの設定ができるようにします。GTMのページ上部の「管理」タブをクリックすると表示される画面で、「外部アカウント リンク」をクリックすると、以下のような画面になります。ここで、GTMにログインしているGoogleアカウントが持っているGAアカウント(持っていない場合は新しく作ってください!)とGAのプロパティが選択できるようになっているので、連携させたいものを選んでください。

GAとの連携

ABテスト用の変数を作成する

さて、いよいよABテストの設定です。ABテストをするためには「Google アナリティクスのウェブテスト」という変数を作成する必要があります。変数とは、アプリに動的に取り込む値を設定したり、アプリから送るデータのフィルタリングに利用される、名前と値のペアです(今回は、アプリに取り込む値の設定に使います)。画面左の「変数」を選ぶと以下のような画面になるので、「新規」をクリックします。

変数の新規作成

変数の作成画面は以下のようになっています。変数の種類に「Google アナリティクスのウェブテスト」を選んでください。

変数の設定

つづいて、各種設定の大まかな説明をします。詳細オプションや有効化のタイミングについては、今回は割愛させていただきます。

Google アナリティクスのアカウント・プロパティ・ビュー

GAとの連携部分です。

ウェブテストの目的

このテストで何を成果とするかを選択します。デフォルトでは、スクリーン数、セッションの長さ、例外数、クラッシュ数の四つしか選べませんが、GAの目標を設定しているとテストの目的に設定することができます。たとえば、特定ボタンのクリックイベントや、ユーザーの課金状況などを設定することもできます。

パターン

ここがABを出し分ける仕組みになります。パターンとは key と value のペアでjsonデータのようになっています。ここで、各パターンで使いたい値を定義していきます。たとえば、アプリのテキスト領域に「Aパターンです。」「Bパターンです。」と出し分けたい場合は、Aパターンで{'text' : 'Aパターンです。'}、Bパターンで{'text' : 'Bパターンです。'}と定義しておけば、アプリ側で「text」という key の値を取得した時に、「Aパターンです。」または「Bパターンです。」のどちらかの値を得ることができます。

コンテナを公開して、ダウンロードする

コンテナは公開することで初めて動作します。画面の右上に「公開」ボタンからコンテナを公開することを忘れないようにしましょう。公開したら、画面上部「バージョン」タグから公開したバージョン(最初は1)を選んでください。以下のような画面になるので、右上の「アクション」→「ダウンロード」をクリックするとGTM-XXXXXXというバイナリファイルがダウンロードされます。

コンテナのダウンロード

ここまでが、GTMでの設定になります。

Androidアプリで各パターンの値を取得する

ここからは、Android Studio での作業になります。

GTMをアプリに導入する

GTMは、GAのライブラリに含まれているので、build.gradledependencies に以下を追加してください。

また、GTMを利用するために必要なパーミッションは、android.permission.INTERNETandroid.permission.ACCESS_NETWORK_STATEなので、必要ならばAndroidManifest.xmlに設定しておいてください。

GTMの初期化

GTMを初期化して、ユーザーがAパターンかBパターンかを確定します。GTMの初期化は、以下のように書きます。アプリの初期化の際に、実施するのが良いと思われます。

ここで、GTM-XXXXXXは自分のコンテナID、R.raw.gtm_default_containerはコンテナを公開した後にダウンロードしたバイナリファイルです。バイナリファイルはres/rawディレクトリに配置すること、バイナリファイル名(元々は「GTM-XXXXXX」)が大文字を含まないようにリネームすることに注意してください(リネームしないとエラーになります)。また、取得したContainerHolderをアプリのどこからでも参照できるようにContainerHolderSingletonというシングルトンクラスを作って、セットしておきます。

値の取得

最後に値の取得を行います。

Container#getString(String key) メソッドで値の取得をすることができます。ここで取得できる値は、ユーザーがどのパターンであるかによって変わります。文言や色などのシンプルなデータなら、GTMから取得した値をそのまま表示すれば良いです。もし、レイアウト自体を大きく変えたい場合は、取得した値をフラグにして読み込むべきレイアウトのxmlを変えるという実装になると思います。

おわりに

この記事では、アプリでABパターンを出し分けるための方法を紹介しました。この時点では、まだテストの解析や開始条件の設定といったことがわからないと思います。それについては、また別の機会に紹介したいと思います。


Posted bysakata

2016年05月9日

sakata

JJUG CCC 2016 Springで登壇します!

カテゴリ
Java 勉強会

Hello world! コンテンツ・メディア第1事業部のjyukutyoこと阪田です。

さて、5/21(土)に開催されるJJUG CCC 2016 Springで登壇することとなりました!私は17時から「Seasar2で作った俺たちのサービスの今」というセッションで話します。

http://www.java-users.jp/?page_id=2396#GH-6

JJUG CCCとは

JJUGとはJapan Java User Group(日本Javaユーザグループ)のことです。日本最大のJavaコミュニティで、4,500人以上の会員がいます。そのJJUGが主催する年に2回のコミュニティイベントがCCC(クロスコミュニティカンファレンス)です。参加者は会を追うごとに増えており、昨年秋のCCCでは当日700名ほどが集まったそうです。今回のCCCは5/21(土)9:30 ~ 20:00、場所はベルサール新宿グランドです。これだけの規模ですが、参加費は無料です。参加したい!という方はこちらから申し込めます。

https://jjug.doorkeeper.jp/events/43045

Seasar2で作った俺たちのサービスの今

弊社では長い間JavaプロジェクトではSeasar2を採用していました。しかし昨年にアナウンスがあり、2016/9/26にSeasar2がサポートを終了することとなりました。公式サイトにもそのことが掲載されています。

http://www.seasar.org/

もちろんサポートが終了するからといって使えなくなるわけではないのですが、新技術への対応などを考え別のフレームワークに移行する決断をしました。現時点で移行が完了した機能もあり、本番環境にて動作しています。このセッションでは、この移行において考えたことや判断理由、作業内容などを話します。詳しくは上記のリンクにあるセッション説明に書いていますので、ぜひ当日ご参加ください。

魅力的なセッション

私のセッションだけでなく、魅力的なセッションが多くあるのもCCCの特長です。日本唯一のJava Championである櫻庭さんのType Annotationのセッション、あのJenkinsを立ち上げた川口さんのJenkins 2.0のセッション、JCPのECメンバである数村さんのJavaデバッガのセッションなど、紹介しきれません。

関西からは私の他に一緒に関西Javaエンジニアの会(関ジャバ)を運営しているirofさんのテスト自動化のセッションや、関ジャバがよくお世話になっている椎葉さんのThymeleaf 3のセッションなどもあります!

参加して絶対に損をしないJavaイベントですので、みなさんもぜひご参加ください!


Posted byKayo


みなさん、こんにちは。コンテンツ・メディア第1事業部インフラ担当の藤本佳世です。前回は「OSインストールの自動化」について、Cobblerを使ったPXEサーバ構築についてお話ししました。今回は、その続き「Kickstart」についてお話ししたいと思います。

read more


Posted byKayo

2016年03月30日

Kayo

OSインストールの自動化

カテゴリ
PXE インフラ

自己紹介

Furyu Tech Blogを読んで下さっているみなさん、初めまして。 コンテンツ・メディア第1事業部のインフラチームに所属していると藤本佳世と申します。今回が初投稿となりますが、これからみなさんに「フリューのインフラ技術」をご紹介できればと思っています。 どうぞよろしくお願い致します。

インフラの仕事

インフラの仕事は、サーバの選定から始まり、OS・ミドルウェアのインストールや監視など様々な仕事があります。 開発メンバーがスムーズに仕事をこなせるよう、日々「縁の下の力持ち」として頑張っています。 今回は、インフラ業務の中でも、「OSインストールの自動化」について、お話したいと思います。

PXEブート

みなさん、「PXEブート」はご存知ですか?

read more



ソーシャルゲーム2部 佐々木です。最近はなかなかコーディングの時間が取れず、ストレスフルな日々を送っています。今回は、半年くらい前に行った Play Framework に関する話題です。

背景

経緯から説明すると、Play Framework 2.1系であるサービス(以後、サービスA)を開発・運用していました。 そのサービスのシステムを流用して新たにサービス(以後、サービスB)を立ち上げることになり、その機会に Play Framework 2.3系に移行することにしました。 ただ、大きなシステム変更があるわけではなく、サービスAとサービスBでは特に大きな機能改修はありませんでした。 そこで、サービスAのシステムの中で再利用性の高い機能をライブラリ化して、サービスA/Bそれぞれがそのライブラリに依存するような形にすれば保守管理しやすいと考えました。

クロスビルドできない

いざ、Build.scala でクロスビルドの設定をしてみると、コンパイルエラーになってしまいました。

ここで問題になったのが、Play Framework の互換性でした。 Play Framework のリリースノートや移行ガイドを見るとわかりますが、Play Framework 2.2系から play.api.mvc.Result 関連のクラスがdeprecatedになり、Play Framework 2.3系では完全に取り除かれました。それにより、単純に依存するライブラリのバージョンを変えるようなクロスビルドの設定だけでは対応できませんでした。

ソースコードのパスを切り替える

そこで、Play Framework 2.1系とPlay Framework 2.3系でソースコードのパスを別々に設定することにしました。

この設定は、Play Framework 2.1系(Scala 2.10.4)でビルドする時には、src/main/scalasrc/main/play21/scalaをコンパイル対象とし、Play Framework 2.3系(not Scala 2.10.4)でビルドする時には、 src/main/scalasrc/main/play23/scalaをコンパイル対象とするものです。

あとは src/main/play--/scalaにそれぞれのplay.api.mvc.Result関連のクラスを定義することによって、当初の目的を達成することができました。

まとめ

WEBフレームワークやライブラリを使う側としては、バージョンアップや互換性にどう向き合うかは、悩ましいところでもあり面白いところでもあると思います。今回の件では、ソースコードのパスを切り替えるという発想に至るまでは紆余曲折あり、互換性を無視したバージョンアップをした Play Framework を憎んだこともありました(笑)が、今となってはこの方法以外無いのではと思っています。別の方法があればぜひぜひ教えていただきたいです!



Hello World! コンテンツ・メディア第1事業部の、jyukutyoこと阪田です。JavaOneではランチボックスが配られるのですが、聞いていたほどおいしくないという感じではなかったです。味はイマイチだけど食べたくないほどではないな、という感じでした。外で食べるとなると確実に$20は超えてしまうので、私はほぼこのランチボックスを食べていました。

私はランチボックスの写真を撮っていなかったので、JavaOneのランチボックス写真をflickrからお借りしました(さくらばさんありがとうございます)。 2014年のものですが、2015年でも同じ感じでした。

Lunchbox, JavaOne 2014 San Francisco

Protecting Java Bytecode from Hackers with the InvokeDynamic Instruction

Javaのバイトコードは高レベルのJVM命令セットです。スタック指向であり、命令フォーマットがあります。

ラムダ式を使った以下のコードがあるとします。

これはバイトコードでは次のように表現されます。

Procyon(https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler)というでコンパイラを使って起動してみます。$java –jar procyon.jar HelloJavaOneWithLamdas.class出力は次のようになります。

Javaのバイトコードへの攻撃としてはリバースエンジニアリングや、重要なルーティンへのバイパス、デコンパイルと変更が容易であることなどです。有名なJavaのデコンパイラは次にようなものです。Procyon + LuytenやCFR、JD、Fernflower、Krakatau、Candleです。 Javaのバイトコード保護としては、コードフロー難読化や名前の難読化、呼び出しの隠蔽などです。ここでObfuscatorという製品をデモします。

次にコンスタントプールとバイトコードについて考えます。コンスタントプールはすべてのシンボル情報を含んでいます。invoke*という命令はメソッド呼び出しに使われます。JVMはメソッド実行の前にスタックが矛盾しないことを要求します。

リフレクションを使って呼び出しを隠蔽することができます。

そうすると、メリットとしてコンスタントプールからMethodRefとFieldRefを取り除けます。デメリットとしてはパフォーマンス、バイトコードサイズのオーバーヘッド、引数や戻り値でボクシング/アンボクシングが必要となること、スーパークラスのメソッドを呼び出せないこと、プライベートメソッドやフィールドへアクセスするときにセキュリティ違反になること、などがあります。

そこで、JSR-292のInvokeDynamicです。Java 7から導入されています。InvokeDynamicを使って呼び出しを隠蔽します。プランとしては、ブートストラップメソッドを生成し、invokevirtual/invokeinterface/invokestaticの呼び出しをinvokedynamicに書き換えます。それにはASMを使います。ASMは低レベルのバイトコード操作のためのライブラリです。SAXのようなVisitor APIとDOMのようなTree APIがあります。ASMでHello Worldすると次のようになります。

ソースコードを読み込み、ASMを使ったコードに書き換えるわけです。ブートストラップを生成するコードはこのようになります。

次に、invoke*の置き換えですが、MethodVisitorを実装します。

visitMethodInsn()メソッドは次のような実装となります。

結果として、たとえばJDででコンパイルするとエラーになります。他のデコンパイラでも読めません。結論としては、invoke*命令はすべて保護できました。さらにパフォーマンスのインパクトはありません。JVMがInvokeDynamicを最適化してくれます。

Having Fun with Javassist

JRebleなどを作っているZEROTURNAROUNDの方のセッション。 XRebelやJRebelでJavassistを多く活用しています。バイトコード操作はいたるところで行われています。Hibernateではプロキシ生成に使われています。主要なユースケースとして、バイトコード操作はJavaのフレームワークにおいてプロキシを生成するために使われています、がその内容だと退屈ですね。 JavassistはリフレクションAPIのような感じです。ClassPoolにCtClassがあり、CtClassにはCtFieldやCtMethod、CtConstがあります。CtMethodにはinsertBefore、insertAfter、instrumentがあります。

ビルド時にメタデータからクラスを生成できます。またはコンパイルしたクラスに対してあとから処理することができます。

こうして、トレーシングを実装したりログを追加したり、AOPを実装したりできます。不要な呼び出しを削除できます。フィールドに直接アクセスしていたところをsetter呼び出しに変えることができます。

次にJava Agentについて。$java –javaagent:agent.jar application.MainでAgentをつけて実行できます。Agentの実装はこうなります。

さらに、META‐INF/MANIFEST.MFにこう書きます。

ClassFileTransformerの実装としては、たとえばこんな感じです。

JRebleプラグインでもこの仕組みを使っています。JRebleプラグインでは、JRebleのコアとSpringやHibernate、EJBといった個別のプラグインがあります。jrebel.jarはすべてのプラグインを含んでいます。クラスをリロードすると、JRebleコアが各プラグインに通知します。そして、実際に設定が更新されたりします。Javassistは各プラグインで使っています。

Beyond top: Command-Line Monitoring on the JVM

サーバがたびたび遅くなる問題がありました。チームはアプリケーションサーバを手動で再起動していました。レスポンスタイムが5分ほどかかることがあありました。何かが起こっています。

事実に基づいてみると、すべてのリクエストが影響を受けていました。JVMは落ちていませんでした。JVMを再起動するとすべてがうまくいきました。何ができるのでしょう?さらなる事実として、フルGCが頻発していました。

ヒープに何があるか、どのアプリケーションコードを実行しているかを確認するために、いいツールがあります。まずvmstat。システムレベルでCPUやメモリ、ディスク、コンテキストスイッチが見れます。topも。プロセスごとのCPUとメモリが見れます。jpsでPIDがわかります。jstackでスレッドの状態がわかります。jcmdは何でもできます。jstatでGCやクラスローダ、コンパイラがわかります。

これで謎は解けます。たとえば、リークを除去する、キャッシュを除去する、機能を削除する、全文検索エンジン…”遅い”には意味がたくさんあります。”CPU負荷が高い”には意味がたくさんあります。データを集めることは危機的状況において極めて重要です。

ほかの役立つツールとしては、ヒープアナライザやプロファイラ、絶え間ないモニタリングやアラート、動的なトレースなどがあります。

Java Community Keynote

Javaコミュニティ(JUG)によるキーノート。これだけ別の大きな会場(Marriott Marquis)でした。

今回は、Java仕様に関わった人やJUGリーダなどが寸劇をするという衝撃的なものでした。ストーリは、JavaのマスコットであるDukeが、未来の世界で歯が生えて(!?)暴れまわっているため、世界を救うために過去にタイムスリップしながら破滅を避けるキーワードを探す、という内容でした。

キーノートのMCはStephen Chinさんで、去年私もJUGリーダとして少し話したことがあり親近感がありました。劇ではジェームズ・ゴスリン本人が登場したり、10年前くらいの世界で「Project Jigsawは完成しているんだろ!?(実際はJava 9なのでまだ)」という少し皮肉ったセリフが出たりと、とても楽しいものでした。

キーワード自体は”Kids are future(未来は子どもたちである)”というものでした。技術的な内容はまったくなく、純粋にJavaのお祭りを楽しむ、そういうセッションでした。

The Rise of 1.0: How Reactive Streams and Akka Streams Change the JVM Ecosystem

リアクティブ・ストリームのお話でした。リアクティブ・ストリームは.NET 3.5で導入されたのが最初です。その後、PlayフレームワークがIterateesを導入しました。AkkaはAkka-IOを、BenがRxJavaを開始しました。ただ2013年時点ではこの3つには違いがありました。Iterateesはpull back-pressureであり、APIが複雑です。Akka-IOはNACK back-pressureであり、低レベルIO、メッセージングAPIです。RxJavaはno back-pressureでいいAPIです。そこでエキスパートグループが創設されました。ゴールは、非同期で、ブロックせず、安全で、純粋に局所抽象化され、同期型も許容するということです。リアクティブ・ストリームには仕様とTCKがあります。バージョン1.0は2015/04/28にリリースされました。

なぜback-pressureなのか?負荷でクラッシュしないようにするためです。back-pressureとは何か? Publisher-Subscriberモデルで考えます。まず、Publisherのpushが早くてSubscriberが遅い場合、Subscriberにはバッファできる何かが必要です。でももしバッファがあふれたら?Subscriberはメッセージを捨てて、Publisherはメッセージを再送する必要があります。カーネルやルータはこうしています。メモリがあるときはバッファを増やせますが、いずれOutOfMemoryになります。Negative ACKnowledgementではバッファオーバーフローは差し迫ったものです。Publisherにペースを落とすか送信を停止してもらわなければなりません。しかしNACKではそれは間に合いません。そうしている間にもメッセージが来るからです。Publisherの速度よりSubscriberの速度が上回っているとき、back-pressureは必要ありません。

リアクティブ・ストリームは動的なPush/Pullです。pushだけでは遅いSubscriberのときに効果がなく、pullだけでは早いSubdcriberのときには遅すぎるのです。解決策としては動的な調整です。遅いSubscriberでは、3つの要素だけバッファに取ります。Publisherはたとえもっと多く遅れる場合でも多くて3つだけにします。これがpull-based-backpressureです。早いSubscriberはもっと要求します。Publisherは要求をためておきます。Publisherは各Subscriberの総要求数をためておき、オーバーフローしないように送ります。

Inter OPでは、異なる実装でもお互いにうまくやれるようにします。RxJavaとAkkaなど。リアクティブ・ストリームがプロトコルとなります。リアクティブ・ストリームはデイリーユースのエンドユーザAPIではありません。これはSPIです。Service Provider Interfaceです。SPIはサードパーティによって実装または拡張されることを意図したAPIです。

Play 2.5はAkka Streamsを使います。ScalaでもJavaでもDSLで同じパワーを得られます。Akka 2.4は2.3とバイナリ互換です。

カニパーティー

これはJavaOneとは直接関係がありませんが、JavaOneの日本人参加者で最終日の夜にカニを食べに行くというイベントが毎年あります。30名以上の方が来られていました。

IMG_1620

カニはダンジネスクラブというサンフランシスコでは有名なカニです。ガーリックソースでローストしており、日本では味わえないおいしさです。手はドロドロになりますので、汚れてもいい服の方がよいです。

話は自然とJavaのこと、いろいろな方と知り合うことができました!

JavaOne全体をふりかえって

最高でした!学べる内容としては、サンフランシスコまで行かなくてもプレゼンテーションの動画を見ても同じです。ただ、刺激という面では、やはり現地で受ける刺激はディスプレイの前で動画を見るよりも何十倍、何百倍も多いです。

英語のセッションということで心配になる方も多いかと思います。ふだん英語の技術文書を読まれている方なら、リスニングに不安があっても大丈夫です!スライドが補助となり、セッションが全部理解できないということはありません。迷うより飛び込んでしまうのが楽です!

私は今年もJavaOneに参加しようと計画しています。2016年のJavaOneは9/18〜22です。日本はちょうどシルバーウィークとなり、2日休暇を取るだけでJavaOneに参加できます!ぜひいっしょにJavaOneに参加しましょう!


Posted bymorioka

2016年02月24日

morioka

try! Swiftに協賛します

カテゴリ
未分類

こんにちは!コンテンツメディア第一事業部の盛岡です。 すでにあと一週間となってますが、3月2日から行われるtry! Swiftというイベントにフリューはスカラシップスポンサーとして協賛しています。

try! Swift

公式HP http://www.tryswiftconf.com/

公式からの説明文を引用すると、「try! Swiftは世界中のSwiftデベロッパーが一堂に会し、知識や技術を互いに共有し高め合うことを目的としたカンファレンスです。」とのことです。

実際に、これだけのスゴ腕エンジニアが集まるのは世界でも稀だと思います。ワクワクしますね。

フリューでのSwift利用について

われわれの手掛けるピクトリンクというサービスのiOS版アプリにおいて、全面的にSwiftを採用しています。

昨年1月に実施した全面リニューアル時に全コードをSwiftに書き換えました。国内のSwift採用事例としては、なかなか規模も大きい方ではないでしょうか。 導入に至るまでの経緯や実際の開発におけるノウハウについても今後紹介出来ればと思いますが、今回は実際に導入してみた感想を書いてみます。

Swiftを導入してみて

Swiftを導入して一番感じるメリットは、短く簡潔なコードを書けることによるコードレビューの効率化ではないかと個人的には思います。

Github + Pull rsequestを主軸とした開発においては、コードを書く時間よりもコードを読む時間が長くなりがちです。

Objective-Cについては、お世辞にも読みやすいソースコードとは言いにくいところがありました。また、ヘッダファイルと実装が分かれていることもレビューする上で時間がかかる要因に成り得ます。

Swiftは楽しい

その他にも色々と利点はあるのですが、Swiftでは、Optionalやクロージャなどのモダンな言語仕様がとても良く作りこまれており、書いていても読んでいても楽しい言語です!作業していて楽しいというのは、開発者として嬉しい限りです。

今後の案件についてもObjective-Cで開発することは多分なくて、Swiftで開発し続けると思います。そして今やSwiftはオープンソースであり、誰でも試せる環境が整ってきています。皆さんも是非 try! Swift してみませんか。