コンテンツ・メディア第1事業部の、jyukutyoこと阪田です。JavaOneではランチボックスが配られるのですが、聞いていたほどおいしくないという感じではなかったです。味はイマイチだけど食べたくないほどではないな、という感じでした。外で食べるとなると確実に$20は超えてしまうので、私はほぼこのランチボックスを食べていました。私はランチボックスの写真を撮っていなかったので、JavaOneのランチボックス写真をflickrからお借りしました(さくらばさんありがとうございます)。2014年のものですが、2015年でも同じ感じでした。InstructionJavaのバイトコードは高レベルのJVM命令セットです。スタック指向であり、命令フォーマットがあります。ラムダ式を使った以下のコードがあるとします。2015");r.run();}</code>これはバイトコードでは次のように表現されます。return</code>Procyon(https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler)というでコンパイラを使って起動してみます。HelloJavaOneWithLamdas.class出力は次のようになります。2015");r.run();}</code>Javaのバイトコードへの攻撃としてはリバースエンジニアリングや、重要なルーティンへのバイパス、デコンパイルと変更が容易であることなどです。有名なJavaのデコンパイラは次にようなものです。LuytenやCFR、JD、Fernflower、Krakatau、Candleです。Javaのバイトコード保護としては、コードフロー難読化や名前の難読化、呼び出しの隠蔽などです。ここでObfuscatorという製品をデモします。次にコンスタントプールとバイトコードについて考えます。コンスタントプールはすべてのシンボル情報を含んでいます。invoke*という命令はメソッド呼び出しに使われます。JVMはメソッド実行の前にスタックが矛盾しないことを要求します。リフレクションを使って呼び出しを隠蔽することができます。2015"})</code>そうすると、メリットとしてコンスタントプールからMethodRefとFieldRefを取り除けます。デメリットとしてはパフォーマンス、バイトコードサイズのオーバーヘッド、引数や戻り値でボクシング/アンボクシングが必要となること、スーパークラスのメソッドを呼び出せないこと、プライベートメソッドやフィールドへアクセスするときにセキュリティ違反になること、などがあります。そこで、JSR-292のInvokeDynamicです。7から導入されています。InvokeDynamicを使って呼び出しを隠蔽します。プランとしては、ブートストラップメソッドを生成し、invokevirtual/invokeinterface/invokestaticの呼び出しをinvokedynamicに書き換えます。それにはASMを使います。ASMは低レベルのバイトコード操作のためのライブラリです。Worldすると次のようになります。1);mv.visitEnd();</code>ソースコードを読み込み、ASMを使ったコードに書き換えるわけです。ブートストラップを生成するコードはこのようになります。13);mv.visitInsn(ACONST_NULL);</code>次に、invoke*の置き換えですが、MethodVisitorを実装します。instructions}}</code>visitMethodInsn()メソッドは次のような実装となります。itf);}}</code>結果として、たとえばJDででコンパイルするとエラーになります。他のデコンパイラでも読めません。結論としては、invoke*命令はすべて保護できました。パフォーマンスのインパクトはありません。JVMがInvokeDynamicを最適化してくれます。JavassistJRebleなどを作っているZEROTURNAROUNDの方のセッション。XRebelやJRebelでJavassistを多く活用しています。バイトコード操作はいたるところで行われています。Hibernateではプロキシ生成に使われています。主要なユースケースとして、バイトコード操作はJavaのフレームワークにおいてプロキシを生成するために使われています、がその内容だと退屈ですね。JavassistはリフレクションAPIのような感じです。ClassPoolにCtClassがあり、CtClassにはCtFieldやCtMethod、CtConstがあります。CtMethodにはinsertBefore、insertAfter、instrumentがあります。{//...}ct.writeFile("/output");}</code>ビルド時にメタデータからクラスを生成できます。コンパイルしたクラスに対してあとから処理することができます。c.newInstance();a.foo("Hello");</code>こうして、トレーシングを実装したりログを追加したり、AOPを実装したりできます。不要な呼び出しを削除できます。フィールドに直接アクセスしていたところをsetter呼び出しに変えることができます。application.MainでAgentをつけて実行できます。Agentの実装はこうなります。code});}}</code>さらに、META‐INF/MANIFEST.MFにこう書きます。Agent</code>ClassFileTransformerの実装としては、たとえばこんな感じです。ct.toBytecode();}}</code>JRebleプラグインでもこの仕組みを使っています。JRebleプラグインでは、JRebleのコアとSpringやHibernate、EJBといった個別のプラグインがあります。jrebel.jarはすべてのプラグインを含んでいます。クラスをリロードすると、JRebleコアが各プラグインに通知します。実際に設定が更新されたりします。Javassistは各プラグインで使っています。JVMサーバがたびたび遅くなる問題がありました。チームはアプリケーションサーバを手動で再起動していました。レスポンスタイムが5分ほどかかることがあありました。何かが起こっています。事実に基づいてみると、すべてのリクエストが影響を受けていました。JVMは落ちていませんでした。JVMを再起動するとすべてがうまくいきました。何ができるのでしょう?さらなる事実として、フルGCが頻発していました。ヒープに何があるか、どのアプリケーションコードを実行しているかを確認するために、いいツールがあります。システムレベルでCPUやメモリ、ディスク、コンテキストスイッチが見れます。プロセスごとのCPUとメモリが見れます。jpsでPIDがわかります。jstackでスレッドの状態がわかります。jcmdは何でもできます。jstatでGCやクラスローダ、コンパイラがわかります。リークを除去する、キャッシュを除去する、機能を削除する、全文検索エンジン...”遅い”には意味がたくさんあります。”CPU負荷が高い”には意味がたくさんあります。データを集めることは危機的状況において極めて重要です。ほかの役立つツールとしては、ヒープアナライザやプロファイラ、絶え間ないモニタリングやアラート、動的なトレースなどがあります。KeynoteJavaコミュニティ(JUG)によるキーノート。Marquis)でした。今回は、Java仕様に関わった人やJUGリーダなどが寸劇をするという衝撃的なものでした。ストーリは、JavaのマスコットであるDukeが、未来の世界で歯が生えて(!?)暴れまわっているため、世界を救うために過去にタイムスリップしながら破滅を避けるキーワードを探す、という内容でした。Chinさんで、去年私もJUGリーダとして少し話したことがあり親近感がありました。9なのでまだ)」という少し皮肉ったセリフが出たりと、とても楽しいものでした。future(未来は子どもたちである)”というものでした。技術的な内容はまったくなく、純粋にJavaのお祭りを楽しむ、そういうセッションでした。Ecosystemリアクティブ・ストリームのお話でした。3.5で導入されたのが最初です。その後、PlayフレームワークがIterateesを導入しました。AkkaはAkka-IOを、BenがRxJavaを開始しました。2013年時点ではこの3つには違いがありました。back-pressureであり、APIが複雑です。back-pressureであり、低レベルIO、メッセージングAPIです。back-pressureでいいAPIです。そこでエキスパートグループが創設されました。ゴールは、非同期で、ブロックせず、安全で、純粋に局所抽象化され、同期型も許容するということです。リアクティブ・ストリームには仕様とTCKがあります。バージョン1.0は2015/04/28にリリースされました。back-pressureなのか?負荷でクラッシュしないようにするためです。Publisher-Subscriberモデルで考えます。Publisherのpushが早くてSubscriberが遅い場合、Subscriberにはバッファできる何かが必要です。バッファがあふれたら?Subscriberはメッセージを捨てて、Publisherはメッセージを再送する必要があります。カーネルやルータはこうしています。メモリがあるときはバッファを増やせますが、いずれOutOfMemoryになります。ACKnowledgementではバッファオーバーフローは差し迫ったものです。Publisherにペースを落とすか送信を停止してもらわなければなりません。NACKではそれは間に合いません。している間にもメッセージが来るからです。Publisherの速度よりSubscriberの速度が上回っているとき、back-pressureは必要ありません。リアクティブ・ストリームは動的なPush/Pullです。pushだけでは遅いSubscriberのときに効果がなく、pullだけでは早いSubdcriberのときには遅すぎるのです。解決策としては動的な調整です。遅いSubscriberでは、3つの要素だけバッファに取ります。Publisherはたとえもっと多く遅れる場合でも多くて3つだけにします。これがpull-based-backpressureです。早いSubscriberはもっと要求します。Publisherは要求をためておきます。Publisherは各Subscriberの総要求数をためておき、オーバーフローしないように送ります。OPでは、異なる実装でもお互いにうまくやれるようにします。RxJavaとAkkaなど。リアクティブ・ストリームがプロトコルとなります。リアクティブ・ストリームはデイリーユースのエンドユーザAPIではありません。Interfaceです。SPIはサードパーティによって実装または拡張されることを意図したAPIです。Streamsを使います。ScalaでもJavaでもDSLで同じパワーを得られます。2.4は2.3とバイナリ互換です。カニパーティーこれはJavaOneとは直接関係がありませんが、JavaOneの日本人参加者で最終日の夜にカニを食べに行くというイベントが毎年あります。30名以上の方が来られていました。カニはダンジネスクラブというサンフランシスコでは有名なカニです。ガーリックソースでローストしており、日本では味わえないおいしさです。手はドロドロになりますので、汚れてもいい服の方がよいです。話は自然とJavaのこと、いろいろな方と知り合うことができました!JavaOne全体をふりかえって最高でした!学べる内容としては、サンフランシスコまで行かなくてもプレゼンテーションの動画を見ても同じです。刺激という面では、やはり現地で受ける刺激はディスプレイの前で動画を見るよりも何十倍、何百倍も多いです。英語のセッションということで心配になる方も多いかと思います。ふだん英語の技術文書を読まれている方なら、リスニングに不安があっても大丈夫です!スライドが補助となり、セッションが全部理解できないということはありません。迷うより飛び込んでしまうのが楽です!私は今年もJavaOneに参加しようと計画しています。2016年のJavaOneは9/18〜22です。