unnamed

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

Crypt 200: Decrypt it(Easy)

ctpm として SECCON 2014 オンライン予選(en) に出ました。25位でした。

上記事の Decrypt it(Easy) を途中から一緒にやりつつ後を引き継いだのに、アホなミス('A')で取りこぼしたので、終了後に解き直したスクリプトを覚え書きとして残す。

なお、「Sage - Open-Source Mathematical Software System」を使っている。

#! /usr/bin/python
# -*- encoding: utf-8 -*-

from sage.all import *

def decode(target):
  if len(str(target)) % 2 == 0:
    print str(hex(target)).decode('hex')

for n,b,c in ([0xb8ae199365,0xffeee,0x8d5051562b],
    [0xb86e78c811, 0xfffee, 0x5ffa0ac1a2], [0x7bd4071e55, 0xfefef, 0x6008ddf867]):
  p,q = map( lambda x : x[0], factor(n) )

  for x in range(p):
    if (x*x + b*x - c) % p == 0:
      x_p = x
      #break
  for x in range(q):
    if (x*x + b*x - c) % q == 0:
      x_q = x
      #break

  decode( crt(x_p, x_q, p,q) )
  decode( crt(p-b-x_p, x_q, p,q) )
  decode( crt(p-b-x_p, q-b-x_q, p,q) )
  decode( crt(x_p, q-b-x_q, p,q) )
  print "-" * 16

実行結果は以下の通り

# sage -python solver.py
SECCO
aNウq
    eh(
W_V"
----------------
2_5
N{Ra_
V
if
  ----------------
b1_N}
U4

%2
----------------

Rabin暗号単射じゃないので一意ではない。意味ある文字は SECCON{Ra_b1_N} ですね。

コアダンプから Java 起動オプションの抜き出し方

この記事は JVM Advent Calendar 2日目 の記事です。

JVM を触っているとコアを吐いて落ちる事がしばしばあります。ええ、しばしばあります。
こういう時にどのようなオプションで起動していたかをうっかり忘れると後々面倒です。
でも、実は簡単に解ります。

簡単なやり方

# strings core.12672 | grep -- -Xmx
-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly -Xmx1500m -Xms1500m -Xloggc:gc.log -XX:+PrintGCDetails -XX:+CMSClassUnloadingEnabled

-Xmxを指定していないときは -XX: とかで grep すると引っ掛かります。

JVM に興味があってちゃんと取りたい人向け

Arguments::_jvm_args_arrayJava 起動オプションを格納した配列で、Arguments::_num_jvm_args がこの配列長(Java 起動オプションの数)です。この静的メンバ変数らはコアダンプが出力された時も存在しています。
なので、gdb で、この配列から要素を引っこ抜いてやれば全 Java 起動オプションが取れます。

たとえば、コアを gdb で起動して以下のコードを実行させれば全 Java 起動オプションが表示されます。

set $num = Arguments::_num_jvm_args
set $i = 0

while($i < $num)
  x/a Arguments::_jvm_args_array + $i
  x/s $__
  set $i++
end

※:バージョンによってはシンボル名が違ったりマングリングされてたりで、Arguments::_num_jvm_args が _ZN9Arguments13_num_jvm_argsE になってたりする場合もあります。

実証 (上のコードを test.gdb として保存しておく)

# java -Xmx100M -Xms100M -XX:+UseConcMarkSweepGC -Xloggc:gc.log -XX:+PrintGCDetails -XX:+CMSClassUnloadingEnabled Test &
[1] 12672
# gcore -o ./core 12672()
Saved corefile ./core.12672
# gdb /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.25.x86_64/jre/bin/java-abrt core.12672 < test.gdb()
gdb-peda$  > > > >
0x7fbd80003120: 0x7fbd80003050
0x7fbd80003050: "-Xmx100M"
0x7fbd80003128: 0x7fbd80003070
0x7fbd80003070: "-Xms100M"
0x7fbd80003130: 0x7fbd80003090
0x7fbd80003090: "-XX:+UseConcMarkSweepGC"
0x7fbd80003138: 0x7fbd80003030
0x7fbd80003030: "-Xloggc:gc.log"
0x7fbd80003140: 0x7fbd80003100
0x7fbd80003100: "-XX:+PrintGCDetails"
0x7fbd80003148: 0x7fbd800030b0
0x7fbd800030b0: "-XX:+CMSClassUnloadingEnabled"
gdb-peda$ quit

おわりに

strings の方が楽でしたね!僕は gdb スクリプト書いてから気付きましたばーかばーか!(つД`)・゚・

CMS GC おさらい

この記事は Java Advent Calendar 2014 の一日目の記事です。

先日の JJUG CCC 2014 FallCMS GC について話してきました。
結構遅めの時間帯にも関わらず、200人規模の部屋がいっぱいに埋まるぐらいの盛況振りで、みなさんGCにお困りなんだなあと実感しました。スライドは以下に公開しています。CMS GC の挙動から GC ログの読み方、どういうケースが厄介なのかを紹介しているので是非ご覧ください!

嬉しいことにセッションの反応は良かったのですが、「遅めの時間帯で頭も疲れてるとガチ話辛い」という声もあったので、今回は CMS GC について比較的重要な点についてだけ簡単におさらいしたいと思います。

オプションについて

@nekop さんの「Java 7 CMS GCの基本的な情報の整理 - nekop's blog」を読めば OK 。

上の記事から追記するとしたら

  • -Xmx と -Xms は同じ値にしたほうが、拡張/シュリンク時に Major GC などの負荷が発生しないのでお勧め。
    • 積極的にシュリンクさせたいなら MaxHeapFreeRatio も変更しないと多くの場合では期待している動作にならないので注意。
    • ちなみに JDK8 以前はこのバグで実はシュリンクできていなかったケースとかもある。
  • -XX:+CMSClassUnloadingEnabled は JDK8 でデフォルト True なので、もう True で良いと思う。
    • JDK 8 で False にしてると、(Metaspaceを使いまくるアプリなら) Metaspace が際限なく増えて最終的に JVM 落ちるんじゃないかな。
    • 有効にすることで増える Remark フェーズの GC ポーズの秒数は下のスライドのログ見れば解る。

他、CMS GC の発生条件のチューニングとして、以下のスライドで CMSInitiatingOccupancyFraction と UseCMSInitiatingOccupancyOnly を紹介しました。

UseCMSInitatingOccupancyOnly を使わずに、チューニングすることも可能ですが、自分が知っている限りでこれが無効の場合の CMS GC 開始条件は、

  • CMS 実行間隔の統計的に、今実行しないとヒープが不足すると判断された場合
  • 最初の CMS 実行時に、ヒープ使用率が CMSBootstrapOccupancy で指定した値を超えていた場合
  • ヒープ領域拡張した結果、GC を行わなくてもメモリ確保に成功した場合
  • 断片化によってまとまったメモリ空間の確保に失敗すると判断された場合

と、これ以外(インクリメンタル CMS やパーマネント領域関係とか)にもあるのでここら辺を一つ一つやるよりは UseCMSInitiatingOccupancyOnly で調整したほうが楽です。

GC ログの読み方について

GC ログの読み方はスライドの P.37 以降に一つ一つ書いているのでそちらで!
特に重要そうな点は以下の通りです。

  • CMS GC と Full GC は別物
    • CMS GC は Initial mark ([1 CMS-initial-mark) と Remark ([1 CMS-remark) フェーズでアプリケーションが止まる。それ以外の時間はアプリは動く。
    • Full GC は Mark Sweep Compaction アルゴリズムであり、実行時はアプリケーションが止まる。
      • promotion failed か concurrent mode failure が出力された時にFullGCが実行される。[Full GC が出力されない場合もある。
      • Full GC対策はスライド参照(P.71から)。
  • CMS: abort preclean due to time」はエラーじゃない。
  • GC locker: Trying a full collection because scavenge failed」が出たら CMS GC は諦めて コンパクションのある GC を使うのがお勧め。

おわりに

CMS GC ではパフォーマンス的にどうにもならない時もあります。どうにもならないことが掴めたら G1GC や Parallel GC、Azul Zingを使うことを検討しましょう。

これ以外にも OpenJDK にはまた新しい GC として G1GC リプレース型の Pauseless GC である Shenandoah がやってきます。JavaOne2014 でも発表していましたが、資料はこっちの方(「Shenandoah An ultra-low pause time Garbage Collector for OpenJDK」)が解りやすいかな。Remembered set絡みの処理が早くなるアイデアで、G1GC より停止時間が優れてる感じっぽいと受け取りましたが、出てくるのはしばらく後ですね。こんな感じで GC との付き合いはしばらく続きそうです。

Java 起動(Launcher)の仕組み

※:この記事は下書き中に本文ががっつり消えたため、知らずに部分的に端折ってるところがあるかもしれません。(´;ω;`)

Java、すなわち JVM (HotSpot) を立ち上げた時、どういった処理が行われているのでしょうか。正確に知りたい場合は OpenJDK のソースコードを読むのが最も確実ですが、概要レベルでどのような処理が行われていて、それがソースコードのどのあたりに書かれているのか案内があった方がすんなりと理解できます。と言うわけで、自分用のメモ書きをちょっとだけ整理してここで公開してみます。

なお、自分の理解をベースに記述しているので間違いが含まれている可能性があります。見つけた場合はそっとコメントか @sugarlife にお教え頂けると大変喜びます。

Java の動作概要について

Java、特に HotSpot の動作概要については、OpenJDK コミュニティによって「HotSpot Runtime Overview」という記事で解説されています。Java の起動時の処理についても「VM Lifecycle」という項目で説明されています。動作の概要を知りたい場合はこれらの記事を読むだけで理解できます。

和訳については有志らが取り組んでいる状況です。Java の動作に興味がある人は是非和訳をしてみませんか:)

この活動を見て、自分もこのメモ書きをちょっと手直しして公開してみようと思った次第です。

Java の起動 (Launcher)

HotSpot Runtime Overview で書かれている起動時における処理内容としては Launcher と JNI_CreateJavaVM が書かれています。Launcher というのは、ユーザが利用する java コマンド等のコマンド群 (java, javac, etc... ) 、およびそこから呼ばれるライブラリ (JLI、libjli) 部分を指します。「Launcher」とだけ書かれていた場合は、java コマンド等のコマンド群を指すことが多いです。
JNI_CreateJavaVM は The invocation API と呼ばれる API の一つで、JVM(HotSpot) そのものをロード & 初期化するメソッドです。現在の実装では一つのプロセスに複数VM は作成不可能なため、一度のみ実行されます。

ここでは主に Launcher 部分について触れて行きます。なお、ソースコードへのリンクは jdk8 の tip(最新コミット) にリンクしています。jdk8 の最新版ではないことに注意してください。最新版は jdk8 の部分を jdk8u に変えることで確認できます。

  • java コマンドを叩く
  • main() / WinMain() [jdk/src/share/bin/main.c]
  • JLI_Launch() [jdk/src/share/bin/java.c]
    • LoadJavaVM() より libjvm をロード。Linux の場合は libjvm.so ファイルをダイナミックロード。
    • HotSpot Runtime Overview に記載されている Launcher の 1. ~ 4. 部分が実行される。
    1. コマンドライン引数の解析。適切な VM を起動するために -client とか -server はランチャ内で利用され、それ以外の引数は JavaVMInitArgs を通じて VM に渡される。
    2. ヒープサイズやコンパイラ種別(client or server)が設定されていない場合、適当な値を設定する。
    3. LD_LIBRARY_PATHやCLASSPATH等の環境変数を設定する。
    4. メインクラスが指定されて居ない場合、jar ファイルのマニフェストファイルからメインクラスを確認する。
  • ContinueInNewThread() [jdk/src/share/bin/java.c]
  • ContinueInNewThread0() [OSによって異なる]
    • non primordial thread を作成、実行する。non primordial thread のエントリポイントは JavaMain()
  • JavaMain() [jdk/src/share/bin/java.c]
    • HotSpot Runtime Overview に記載されている 5. 以降の処理が行われる。
    1. (ContinueInNewThread0() で non primordial thread を作成し、)JNI_CreateJavaVM()を呼んで VM を作成・初期化する。新しいスレッド(non primordial thread)を作成しているのは、この処理自体を行っているスレッド(primordial thread)が、環境によっては色々な制限があり、VMの作成上で制約(Windows上でのスタックサイズなどによる制約など)があるため。
    2. メインクラスを読み込んで、メインクラスからメインメソッドの属性を取得する。
      • LoadMainClass() 以降の処理。メインメソッドを取得しているのは GetStaticMethodID()。
    3. CallStaticVoidMethod() とコマンドラインに渡された引数を使用してメインメソッドを呼び出す。
    4. メインメソッドが完了したら、待機中の例外 (pending exception) がないか確認し、exit status が渡されてないことを確認する。例外は ExceptionOccurred() でクリアされる。メソッドが成功していれば戻り値は 0 に、そうでなければ呼び出し元のプロセスに返却される。
    5. メインスレッドは DetachCurrentThread() によりデタッチされる。これによりスレッドカウントをデクリメントし、DestroyJavaVM() を安全に呼び出し、且つこのスレッドが VM 内の操作やスタック上に Java フレームが存在しないことを保証できる。
      • JavaMain()は最終的に LEAVE() マクロを呼び出し、DetachCurrentThread()、DestroyJavaVM()を呼んでいる。

以上、Launcher 編でした。

JNI_CreateJavaVM() について。

ここは真面目にやると深いので、

まとめ

OpenJDKこわい。

JJUG CCC 2014 Fall で Concurrent Mark & Sweep Garbage Collection について話します。良かったらマサカリを置いて来てね!

JavaOne 2014 で発表してきた。

JavaOne2014JVM 監視・トラブル解析支援ツールである HeapStats について発表してきました。

Session ID: BOF3108
Session Title: Troubleshooting with Serviceability and the New Runtime Monitoring Tool: HeapStats
Venue / Room: Hilton - Continental Ballroom 5
Date and Time: 9/30/14, 20:00 - 20:45

発表スライドは こちら からダウンロードできます。色々と課題も見えた発表でしたが、自分の関わっているプロダクトがあの JavaOne で名乗りを上げ、なおかつ(同時に行った出展なども通じて)好反応を得られたのは感無量でした。
発表や出展の様子は今週末の10/18(土)に行われる JJUG 主催の JavaOne 2014 サンフランシスコ報告会 Tokyo でもう一人のスピーカーが発表する予定です。

もし HeapStats についてコメントや質問、要望などがありましたら メーリングリスト に是非投稿お願いします:) 発表や説明して欲しいなーという方は @sugarlife に Mention ください!ステッカーばらまきに行きます!

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 」はその内もっと掘り下げていくことになりそうです。