unnamed

Javaとか、http://twitter.com/sugarlife

JDK 8 新機能ダイジェスト (JDK 8 Features) #java

この記事は Java Advent Calendar 15 日目です!
14日目は @megascus さんの
動的SQLでPreparedStatement+プレースホルダを使用する - 水まんじゅう でした。
明日は @cero_t さんです。

まえがき

いよいよ JDK 8 が来年の3月に正式リリースされます。素晴らしいことに Java Japan User Group の皆様の blog や記事、 JJUG Night、CCC などの勉強会やカンファレンスなど、JDK 8 の新機能が紹介されている場が多いので、既にある程度知っている人も多いのではないでしょうか。しかし、JDK 8 全体としてどのような機能が加わるのか、それを把握する方法がよく解らない人もいらっしゃると思います。ここではどうすれば JDK 8 の新機能を確認できるのか、そして新機能はどう言ったものがあるのか簡単なダイジェストを紹介します。

なお、JDK 8 から導入されるクラスやメソッドは何かという観点での変更点確認は torutk さんの記事に纏まっていますので、そちらを参考に!

JDK Enhancement Proposal

Java 関連の周辺技術標準化は JCP(Java Community Process) によって行われ、新しい技術仕様や改訂仕様(既存技術仕様の改訂)は JSR (Java Specification Request) として提案され、標準化に関する作業が管理されます。
では、JSR を追って行けば JDK の新機能が解るのか?実はそれは違っていて、JDK で何かしらの新機能を加える場合、その内容は JEP (JDK Enhancement-Proposal) として管理されています。JDK 8 の機能部分は、Oracle 社独自の変更(解りやすい例としてFlight Recorder周り)以外の変更点は、OpenJDK 8 プロジェクトの Features から確認できます。今回はこの JEP についてダイジェストをまとめてみました。

JDK 8 Features ダイジェスト

と言うわけでダイジェストです。

126 Lambda Expressions & Virtual Extension Methods

JDK8 の目玉の一つ、Lambda。@bitter_fox さんが素晴らしい発表JJUG CCC 2013 Fallでされたのでそちらを確認しましょう。

138 Autoconf-Based Build System

ビルドシステムの簡素化&並列化を目指して autoconf (./configure style) ビルドセットアップの導入、Makefileのリファクタなど。エンドユーザ(※ここではJava言語を使ってコード書く人)は関係なし。JVMをビルドする人は楽になる(かも)。
個人的にはビルドシステムの改善はどこのプロジェクトでも課題になりやすい感がありますね。

160 Lambda-Form Representation for Method Handles

Lambda関係。メソッドハンドル / invokedynamic の改善。JSR 292の延長。

161 Compact Profiles

Profileの導入。リソースが制限されたデバイスでも動作するように各用途に応じたプロファイルを準備できるようにする。
これは Java ME との統合の一環(JDK8からJava SEとJava MEの統合が目指されている)の拡張。

162 Prepare for Modularization

Project Jigsaw (モジュール化) の前準備。Jigsaw は 元々 JDK 8 からの予定だったが、JDK 9 にずれ込んだ。

164 Leverage CPU Instructions for AES Cryptography

AES暗号化処理の高速化。x86 コアを使っている場合に有効。各環境ごとに対応してる JVM ならではか。

174 Nashorn JavaScript Engine

Nashorn. Rhino 後継の JVM ベースの JavaScript 実装。

176 Mechanical Checking of Caller-Sensitive Methods

セキュリティ関連。エンドユーザは余り関係なし。

179 Document JDK API Support and Stability

Jigsaw、および162:Modularization に関連。JDK APIサポート、及び安定性の文書化。

142 Reduce Cache Contention on Specified Fields

マルチスレッドアプリにおけるキャッシング改善。JVMレイヤの変更で、アプリレイヤは無関係(影響なし)。

122 Remove the Permanent Generation

パーマメント領域の削除。ヒープ領域への統合。
以下、このJEPのソースコードからの確認内容。
PermGenがなくなったので、クラスのアンロードはクラスローダのライフサイクル(破棄)と同期するようになる。
他、UseCompressedKlassPointers が true の場合(追記:デフォルトは環境依存)は、ClassMetaspaceSize(デフォルト100M。指定する場合はKlassEncodingMetaspaceMax以下にしないとUseCompressedKlassPointersが false になる)のMetaspaceを作成する。ここら辺の各種オプション等は、GA 出てから再確認してから別途掲載します。

ソースコード等の情報は以下のように取得する。

173 Retire Some Rarely-Used GC Combinations

テストやメンテナンスコスト削減のため、滅多に使われてない GC 組み合わせを削除。
具体的には

  • -XX:-UseParNewGC -XX:+UseConcMarkSweepGC
  • -XX:+UseParNewGC
  • -Xincgc / -XX:+CMSIncrementalMode

を実行した場合、警告が出力される。

136 Enhanced Verification Errors

JVM's bytecode verifier の拡張。(VerifyError)

148 Small VM

3mb以下のvm作成をサポート。JavaME統合との一貫。

171 Fence Intrinsics

メモリフェンスintrinsics。エンドユーザには影響なし。省略。

153 Launch JavaFX Applications

java コマンドラインから JavaFX アプリがランチできるようになるよ!

103 Parallel Array Sorting

java.util.Arrays に配列をパラレルにソートするメソッド(parallelSort)を追加。JSR 166 (Fork/Join) 関連。

107 Bulk Data Operations for Collections

Lambda関連。ざっくり言うと「filter/map/reduce for Java

109 Enhance Core Libraries with Lambda

Lambda。

112 Charset Implementation Improvements

Charsetの改善。目的はメンテナンス性と性能。

119 javax.lang.model Implementation Backed by Core Reflection

コアリフレクションによるjavax.lang.model実装(読んで字のごとく)。

135 Base64 Encoding & Decoding

Base64 エンコード/デコードの標準APIの提供。

149 Reduce Core-Library Memory Usage

性能に問題を与えない範囲でのコアライブラリによるメモリ消費量の削減。

150 Date & Time API

新たな日付APIの提供。詳細は kis さんの記事が参考になります。また、このAPIの象徴的なツイートは以下の通り。


155 Concurrency Updates

JavaSE5から導入された並行処理用のAPI(java.util.concurrent)の更新。要点は次の三つ。

  • スケーラブルに更新可能な変数(Adder(DoubleAdder、LongAdder等)、Accumulator(DoubleAccumulator、LongAccumulator等))の追加
  • ConcurrentHashMap に対するキャッシュ指向の機能拡張(メモリ消費削減、シーケンシャル・並行処理のサポート)
  • ForkJoinPool の改良(パフォーマンス改善など)
170 JDBC 4.2

JDBCのマイナー拡張。

177 Optimize java.text.DecimalFormat.format

DemicalFormatの最適化。ゴールは2倍の速度改善らしい(micro-benchmark)。

178 Statically-Linked JNI Libraries

statically linked native librariesのサポート(JNI)

180 Handle Frequent HashMap Collisions with Balanced Trees

java.util.HashMap のパフォーマンス改善。バランス木による頻繁な HashMap 衝突のハンドリングによって改善を図る。

184 HTTP URL Permissions

IPアドレスレベルに基づいたHTTP URLパーミッションの追加。

185 JAXP 1.5: Restrict Fetching of External Resources

JAXP 1.5の更新。メインは外部リソース取得の制限。

core/lang 関連の JEP

以下の JEP により、言語(主にアノテーションJavaDoc絡み)に変更が入りました。

  • 101 Generalized Target-Type Inference
  • 104 Annotations on Java Types
  • 105 DocTree API
  • 106 Add Javadoc to javax.tools
  • 117 Remove the Annotation-Processing Tool (apt)
  • 118 Access to Parameter Names at Runtime
  • 120 Repeating Annotations
  • 139 Enhance javac to Improve Build Speed
  • 172 DocLint
core/i18n 関連の JEP

国際化に関する変更は、主に Unicode 6.2 がサポートされたことがメイントピックだと思われます。

  • 127 Improve Locale Data Packaging and Adopt Unicode CLDR Data
  • 128 BCP 47 Locale Matching
  • 133 Unicode 6.2
core/sec 関連のJEP

セキュリティ関する以下の機能がサポートされました。新たにサポートされた暗号化方式は何かを知りたい場合は、JEP 115: AEAD CipherSuites を確認しましょう。

  • 113 MS-SFU Kerberos 5 Extensions
  • 114 TLS Server Name Indication (SNI) Extension
  • 115 AEAD CipherSuites
  • 121 Stronger Algorithms for Password-Based Encryption
  • 123 Configurable Secure Random-Number Generation
  • 124 Enhance the Certificate Revocation-Checking API
  • 129 NSA Suite B Cryptographic Algorithms
  • 130 SHA-224 Message Digests
  • 131 PKCS#11 Crypto Provider for 64-bit Windows
  • 140 Limited doPrivileged
  • 166 Overhaul JKS-JCEKS-PKCS12 Keystores

まとめ

以上、JDK 8 新機能のダイジェストでした!いかがでしたでしょうか、意外にこんな機能も追加されていたんだなーとか何かの気付きになれたら幸いです。
個人的には「 JEP 122: Remove the Permanent Generation 」と「 JEP 155: Concurrency Updates 」はその内もっと掘り下げていくことになりそうです。

Groovy で JVM ログ解析 (ClassHistogram編) #gadvent #java

Groovy で 面倒な JVM ログを解析する (ClassHistogram)

前置き

この記事はG*(Groovy, Grails ..) Advent Calendar 2013 - Qiita [キータ]の10日目です。
前日は研究室の先輩 @tetsurokitaharaさんのGracenote with Groovy でした。

JVM(hotspot) は好きですが Java は余り書かず、作りこむなら Scala、速度が欲しいなら C、ログの解析なら awk/sedRuby 等で済ます日々ですが、Java のログなので Groovy でさっと処理してしまおうと考え取り組んでみました。どうせなので groovysh で扱える仮想配列として出力し、後々好きな様に加工できるようにしました。
この題目は7日目の@nobusueさんのGroovyでGCログ解析と多少被ってますが、別のログが対象ということで許してください><

JVM ログで出力される ClassHistogram とは

一般的には OutOfMemoryError が発生した場合などで利用するクラス統計情報で、現在実行中の Java プロセスに存在する各クラスのインスタンス数、バイト数が含まれています。
JVM 起動オプションに -XX:+PrintClassHistogram を指定し、SIGQUIT (kill -3 ) を送出すれば以下のようなログが出力されます。

num   #instances    #bytes  class name
--------------------------------------
  1:     24868     3398080  <no name>
  2:     24868     2598976  <methodKlass>
  3:      2813     2432352  [I
  4:      1970     2415680  <constantPoolKlass>
  5:      1970     1873040  <instanceKlassKlass>
  6:      1873     1661760  <constantPoolCacheKlass>
(中略)
1105:         1          16  sun.reflect.GeneratedMethodAccessor3
1106:         1          16  sun.awt.X11.XProtocol$1
Total   172945    22390368

これを間隔を置いて複数回出力させれば、各クラスが時系列にそってどのように増減しているかが調べることが可能です。解りやすい例だと、あるクラスのバイト数が常に増大していれば、明らかにそのオブジェクト(を生成している部分)でメモリリークを起こしてることが判明します。
このログで面倒なのは、複数クラスローダが存在する場合です。クラスローダAとクラスローダBで同じクラスがロードされていると、それは別物扱いなので同じクラス名の情報が重複して出力されます。その上このログからはクラスローダ情報はばっさり捨てられてるので、今回は同じものとして加算しています。

ログから各クラスの時系列ごとの統計情報を解析する

というわけで仮想配列を出力するコードです。実は何気に殆ど初 Groovy だったりするので所々酷いところがあると思います。。

一枚目の gist のコードを保存し、二枚目の gist の通り groovysh で呼び出して仮想配列として出力できます。その後は、例えば以下のようにすればクラス一覧を出力しつつ、各自系列ごとのランク、インスタンス、バイト数情報が引き出せます。

import static ClassHistrogram.*
ch = calc("*log")
ch.each{ klass, timeline ->
  println "{${klass}:"
  timeline.each{ time, value ->
    println "  {${time}:{rank:${value[0]},instance:${value[1]},byte:${value[2]}}}"
  }
  println "}"
}

---出力例---
{sun.java2d.pipe.LoopPipe:
  {0:{rank:1040,instance:1,byte:16}}
  {1:{rank:1057,instance:1,byte:16}}
  {2:{rank:1071,instance:1,byte:16}}
  {3:{rank:1079,instance:1,byte:16}}
  {4:{rank:1079,instance:1,byte:16}}
  {5:{rank:1081,instance:1,byte:16}}
  {6:{rank:1082,instance:1,byte:16}}
  {7:{rank:1079,instance:1,byte:16}}
  {8:{rank:1078,instance:1,byte:16}}
  {9:{rank:1078,instance:1,byte:16}}
  {10:{rank:1078,instance:1,byte:16}}
}
---

このように LTSV 形式に出力するのもよし、CSV ファイル形式に出力や特定クラスの情報だけ引っこ抜くのも良しで、加工しやすいのではないかと思います。

以上です、次は https://twitter.com/setoazusa:title@setoazusa さんの番です!

「Java解析ツールバトル」に登壇しました & HeapStats の動かし方について #jjug

JJUG ナイト・セミナー 「Java解析ツールバトル」に HeapStats 陣営でコミッターとして参加してきました!

今回のJJUGでは、自分達の JVM に深く密着してパフォーマンスに心血を注いでいる HeapStats、最近 OSS 化された Java だけでなく SQL 実行計画まで総合的に診断する EndoSnipe、昨日の OracleJDK 7u40のリリースで公式に JDK に付属された Java Flight Recorder と twitter4j の開発者であるモデレータが過去に開発された 侍 の三つ巴でディスカッションを行いました。
数々のプロジェクトやサービスで利用されている Java だからこそ、障害や性能問題に悩まされる人の数も多いと思われます。障害解析の手助けになるツール、それも今回参加した3つの内2つは日本人によって開発されていることもあり、かなりの盛況ぶりだったと思います:)

自分達のHeapStatsの発表資料はSlideshareで公開しています。興味のある方はぜひご覧ください。


ディスカッションでは時間の関係上、駆け足での説明だったため、「HeapStats はどうやって動かすの?」という最初の一歩をもう少し詳しく補足していきたいと思います。

HeapStatsのインストール

HeapStats インストール条件

性能に心血を注いだ結果として、JVMに手を突っ込み、一部のコードをアセンブラ化している等が原因で、HeapStatsを動かすためには以下の環境である必要があります

  • HotSpotであること
    • OpenJDK 6以降, あるいは OracleJDK 6以降
    • OpenJDK の場合は debuginfo パッケージもインストールする必要があります。
  • x86 または AMD64Linux であること
HeapStats インストール&動作方法

HeapStats をインストールするためにはバイナリからインストールする方法と、ソースからビルドする方法があります。今回はバイナリからインストールする方法を紹介します。

  • バイナリをここから取得してインストールする。
    • $ rpm -ivh heapstats-agent-[version].[CPU命令セット].[Linux dist].[アーキテクチャ].rpm
    • CPU命令セットの部分は解らない場合は何も記載されていない物を利用して下さい。
      • 利用している環境がサポートしているCPU命令セットを確認したい場合、"/proc/cpuinfo" の "flags" を見ることで確認ができます。
      • avxが書かれている場合はavxを、avxはないがsse4が書かれている場合はsse4を、それ以外は無印を利用するのがお勧めです。
    • Linux dist の fc は Fedora, el は RedHat Enterprise Linux を指します。
  • 監視させたい Java プログラムの起動オプションに以下を追加して実行する。
    • -agentlib:heapstats
    • 既に動作している Java プロセスに対してアタッチする場合は こちら を確認して下さい。
  • 実行ディレクトリに heapstats.csv, heapstats.dat が出力される。
    • analyzer を利用して可視化が行えます。
    • 出力フォルダは設定ファイル /etc/heapstats/heapstats.conf (デフォルト) を編集することで変更できます。

以上で HeapStats は実行している Java プロセスを常時監視しつつ各種情報を取得し、故障発生時には解析に必要な情報を根こそぎ取得するようになります!

HeapStatsの各種設定やアナライザによる可視化は公式サイトをご確認下さい。日本語サイトも準備されています!

公式配布のソフトウェアだけでWindowsでMOVファイルをWMVファイルに変換する方法

不慣れな人が動画変換をする場合、無料でやるためによく解らないフリーウェアを入れて変換することが多い。しかしMOVからWMVに変換するだけなら、公式で配布しているソフトウェア(無料)で変換することができた。検索してもやり方が見つかり辛いので備忘録として残す。

MP4(H.264)に変換したい場合は、餅は餅屋ということでここらへんを参考にすると良い。

前準備

  • Microsoft Expression Encoder 4 を入手して、インストールする。
    • 環境によっては.NET Framework 4.0や、Silverlightのインストールが求められる。それぞれのダウンロード先は表示されるので手順に従ってインストールする。
  • Quick Time を入手して、インストールする。
    • Expression EncoderだけではMOVファイルを認識できないが、Quick Timeをインストールすれば認識できる。

これらのソフトウェアは有料(Pro)版も販売されているが、無料版も用意されているのでそれを使う。上記リンク先は全部無料版なので、ここでは気にせず導入すると良い。

変換

  1. Microsoft Expression Encoder 4を起動する。
  2. 画面下部のメディアコンテンツ欄に変換したいMOVファイルをドラッグ&ドロップする
  3. エンコードボタンを押す。
    1. 変換形式を変えたい場合は、画面右側のエンコードタブの出力形式から選ぶ。
  4. エンコードが完了したら、画面右側の出力タブをクリックする。
  5. 真ん中あたりにあるジョブ出力のディレクトリ先に変換済みのファイル場所が表示されているので、そのディレクトリを開けば変換済みファイルがある。

Enjoy :)

JavaでFull GCを実行する方法

Full GCを任意のタイミングで実行させ、負荷の高い処理に備えておくという戦略を取りたい時がたまにあります。基本的にはチューニングで解決すべきですが、緊急or暫定策の備忘録として。

jmap -histo:live <pid>

LinuxはJDK5から、WindowsはJDK6から利用可能。生存中のオブジェクトのみ抽出したメモリーマップを作成するために、直前にFull GCを実行するのでこれを利用する。
対象のJavaプロセスを実行しているユーザで実行する必要があるので注意。

jcmd <pid> GC.heap_dump <output_filename>

Linux、WindowsともにJDK7から。これも上のjmap -histo:live と同じく、生存中のオブジェクトのみ抽出するためにFull GCを実行する。これもJavaプロセス実行ユーザと同じユーザで実行する。

Full GCを実行する機能について

JDKでは、恐らく上記の生存オブジェクトのヒープ情報を取得する(HeapInspection)場合でしか、明示的にFull GCを実行する方法は準備されていないと思われる。
実際に呼び出されるコードは以下。

./hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue)から以下を呼ぶ
VM_GC_Operation(0 /* total collections, dummy, ignored */,
                GCCause::_heap_inspection /* GC Cause */,
                0 /* total full collections, dummy, ignored */,
                request_full_gc /* live=true, all=false */) 

GCを起動させる方法(追記)

以下はGCが実行され、条件によってはFull GCが呼ばれる。これは上のVM_GC_Operationとは別ルートで、この記事のコメントにあるルートで呼ばれる。条件については未確認なので注意。条件についてはとは書いているが、基本的に Full GC になることを期待できる…はず。

  • Runtime.getRuntime().gc() / System.gc()
  • jcmd <pid> GC.run
  • jconsole の 「Perform GC」ボタン

以下は上のJVM_GC_OperationでFullGCがリクエストされない形で呼ばれるため、普通のGCが起動される。GCなのでヒープ状況次第ではFullGCも呼ばれる。

  • jmap -histo <pid>

Java SE 7 JavaDoc 日本語版 公開

前回の記事でJava SE 7 の日本語版 JavaDoc は公開されていないと書きましたが、先日の Java Day Tokyo 2013 で公開されました!
なんてタイミングだ\(^o^)/

ともあれ大変喜ばしい事です。一部英語の部分もありますが、順次アップデートされるそうです。日本オラクル社と寺田さんの尽力に感謝します!#てらだよしおあいしてる

Java SE 7 JavaDoc公開先:http://www.oracle.com/technetwork/jp/java/javase/documentation/

最新のOpenJDK8のJavaDoc (Java API) #yutori_history

こちらはゆとり Advent Calendar の 12 日目です。おすしたべたいので参加しました!
昨日は @mike_neck さんの mike、mikeなるままに…: ゆとりさんが鮨を奢ってくれるそうなので、感謝の気持を込めて、たくさんのプロセスに「sushi」と言わせてみた でした。
ゆとり Advent Calendar : ATND

ゆとりさん転職おめでとうございます!出会ったのは #glassfishjp で発表した日だったような気がします。GlassFish寿司おごって下さい!

そんなゆとりさんですがこんな事を呼びかけていました。


残念なことに現在の最新版である JDK7 は日本語APIドキュメントが公開されていない状況です(2013/05/15追記)公開されました。これを受けて今年の夏に出るはずだった JDK8 は、OpenJDK8をベースに有志で作成しようと先月呼び掛けておられました。私も参加します!

当初、JDK8は夏にGAリリースだったので、しばらくしたらすぐ動き始めるかなと思いきや、JDK8はhttp://mail.openjdk.java.net/pipermail/jdk8-dev/2013-April/002336.html:title:MLでの周知にもある通り、GAが来年の3月14日にズレることになりました。なので、実際にやり始めるのはもうしばらく後になると思いますが、折角なので最新のOpenJDK8のAPIを作って用意しておきましょう。

と、思ったら普通に最新(2013/05/12現在 b89)のAPIが公開されてました。
Overview (Java Platform SE 8 b89)

今日の気付き:さきにしらべとけゆとり


明日は @eiryu さんの番です!