Java8で気になること

Java8が出たみたいですが、ラムダうんぬんもさることながら、元インフラ系として気になるのはPermGenがなくなったことです。 -XX:MaxPermSizeを設定しなくてもOOMEが起きなくなったんだと思うので一見グッドニュースだけれども、クラス等のロード自体がなくなったわけではなく、ロード先が変わっただけだと思うので、今度はそっちの領域(ネイティブヒープ?)のきちんとした見積もりが必要になる。なるんだけれどもPermGenという形で分かれてないので見積もりはひょっとしたら難しくなるのかもしれない。実際JRockitのときはそんな話もあった。そんな感じです。

jBPM6+Java EE 6 ベースのサンプルアプリケーション

もう半年以上前の話になるのですが、仕事でワークフローエンジンjBPM6のベータ版と、JBoss AS7の組み合わせを使う必要があって、自分でも独自に検証していました。その過程を書いておかないと忘れそうな気がするのでここに記します。思い出しながら書くので記憶違いがあるかもしれませんがご容赦を。

用意するもの

Java EE 6対応のアプリケーションサーバRDBMS,それにjBPMのランタイムライブラリです。上記ソースコードJBoss AS 7 + MySQLで動くようにしています。他の組み合わせを使う場合、 src/main/resources/META-INF/persistence.xml においてJPAプロバイダの設定を書き換える必要があります。
また、jBPMのランタイムについてはMavenで取得するようなpomを書いてやるとよいと思います。(手間だったので本稿の時点では作っていませんが、仕事のほうではそうしました)

jBPMのバージョン

6.0.0 beta5 で検証したのが最後だった気がします。その後、6.1系も出てきているようなので今でもちゃんと動くのかどうか不明です。

jBPM5から6に変わるときは、多くの非互換な変更が行われ、そのため5ベースで書いていたコードは大幅な書き直しが必要でした。今はそうなっていないことを祈るばかりです。

あとbetaだからか動作自体にも色々不安定なところもありました。例:
https://community.jboss.org/thread/230840

要素技術の説明

サンプルではJava EE 6のServlet, CDI, JPA, EJBを使っています。なぜCDI/JPA/EJBを使うのか?と思われる方もいるかもしれませんが、少なくともjBPM6 betaの段階では、jBPMのライブラリ自体が、CDIJPAを使うことが前提とされているか、その組み合わせでしかテストされていないのではないかといった具合だったので、使わざるを得なかったというのが実態です。

また、Servletにしていますが、本例のような場合は、どうせJava EE 6に依存するのだから、いっそJAX-RSを使うのがよいです。 ただしJAX-RSだと、私の記憶が正しければ、Servletと異なりJAX-RSのリソースとCDIの組み合わせでは、トランザクションの面倒を見てくれません。トランザクション境界を構成するには、「JAX-RSのリソースであり、なおかつステートレスセッションBeanでもある」ようなクラスとして作成する必要があります。

Javaから離れて半年以上経つので忘れちゃったけど、そんな感じでやっていた気がします。

おまけ

ワークフローの図をエンジンに読み込ませるのにBPMNという仕様を使うのですが、jBPMではそのBPMNのグラフィカルなエディタも作られていました。

当初はGEFベースのEclipseプラグインとして作られていたのですが、紆余曲折あってエディタ機能はWebアプリ化されたり別実装になったりして、従来からあったプラグインは今後積極的に開発されないことになっていました。(その後どうなったのかは追っていません。)

このEclipseプラグインを仕事で大幅に改造したのですが、その過程でわかったことは、このプラグインにせよ、その後継とすべく開発されているWebベースのエディタにせよ、BPMN仕様の解釈を間違っている部分があるのではないか?ということです。具体的には以下です。
https://community.jboss.org/thread/228192
これ回答ないのですがやはりおかしい。おかしいがBPMNの相互運用性で困る人がいないので、放置されているのが現状なんだと思われます。

シャープ HDD/DVDレコーダーのHDD換装

DV-HRD30というシャープの2005年あたりのモデルのHDD/DVDレコーダの、HDDが不良でカクンカクンと音がするので、蓋を開けてHDDを同一型番のものに交換しました。ただし、一筋縄ではいかなかったので、ネット情報を探しました。情報は色々見つかるのですが、内容が古かったり、複数の場所を参照する必要があり時間を要してしまったので、整理し、以下に記録として残すことにします。

主な情報源 http://www.geocities.jp/hrd774/ など

HDDの取り外しと換装用HDDの入手

ふたはドライバで簡単に外れます。高電圧部分などもあると思うので自己責任になります。中身は一昔前のパソコンで使われていた普通の3.5インチIDE規格のHDDで、Hitachi GST社製Deskstar HDS722525VLAT80 という250GBのものが入っていました。

ネット情報によると、より大容量のモデルに換装する例もあるようですが、私はHDDの不良を解決したいだけですので、同一型番のものを秋葉原の中古ショップで見つけ、購入しました。ソフマップの中古品店で確か2014/03に2,500円ほどでした。

データのコピー

HDDには詳細不明ながらシステム用の領域が数MB〜数百MBあるようですので、レコーダーから取り外した旧HDDの内容を可能な限り新HDDにサルベージします。「これdo台」などのHDDコピー専用の機械が売られているので、それを使うこともできますが、私は持っていないので適当なPCでLinux を立ち上げ、それにUSB接続で新旧のHDDをつないでddコマンドでコピーします。もともと持っていた、IDE HDDをUSB接続するHDDケースに加え、センチュリーのUD-500SAというケーブルセットを買ってつなぎました。

# コマンドは思い起こしで書いています
dd if=/dev/sde of=/dev/sdf bs=1M conv=noerror

案の定、途中でI/O errorでフリーズしてしまいましたが、今回は幸いにも動作に必要な部分はコピーできたようです。

新HDDのセットアップ

新HDDをレコーダーに戻しても、それだけだと録画などができません。たとえ同一型番であっても、HDDの中には一台一台ごとにIDが振ってあるらしく、そのIDがレコーダー内に登録されているIDと異なると、利用できないように造られているのです。

そこで、サービスモードという設定画面で、新HDDのIDをレコーダーに再登録することになります。以前は本体付属のリモコンだけでサービスモードに入ることが出来たようなのですが、最近のファームウェアでは、付属リモコンだけでは駄目で、メーカーのサービスマンが持つ特殊なリモコンのボタンを押す必要があります。

しかし当然のことながら、そんなリモコンは持っていないので、代わりに特殊リモコンと同じ信号をなんらかの形でレコーダーに送ってやります。今回はたまたま、PCから信号を登録できる「クロッサム」という学習リモコンがあったので、これを使いました。

サービスモードのリモコン信号

シャープのHDDレコーダーのサービスモードのリモコン信号について以下のブログに記事がありました。

カラーバー(RC1) 0xAA 5A 8F 30 F5 01
カラーバー(RC2) 0xAA 5A 8F 31 F5 11
カラーバー(RC3) 0xAA 5A 8F 32 F5 21
http://yokamaro.blog130.fc2.com/blog-entry-447.html

RC1,2,3と3種類あるのは、3つのうちどれかということのようです。私の場合RC1でうまくいきました。
こうしたリモコン信号の情報をクロッサムが読み込める形式に変換するスクリプトは以下のページに説明されていました。

http://www.geocities.jp/shrkn65/remocon/panasonic_bsd.htm

このスクリプトを実際に流してみた結果は以下のとおりです。

ooharak@air ~
$ perl cro.pl AA 5A 8F 30 F5 01
"00,04,22,26,04,00,26,04,00,26,04,00,73,0c,00,34,21,00,9a,10,00,26,04,00,6c,dc,02,20,10,10,10,10,10,11,01,01,11,10,00,10,00,01,10,01,01,01,11,11,00,00,00,03,fe,32,"

ooharak@air ~
$ perl cro.pl AA 5A 8F 31 F5 11
"00,04,22,26,04,00,26,04,00,26,04,00,73,0c,00,34,21,00,9a,10,00,26,04,00,6c,dc,02,20,10,10,10,10,10,11,01,01,11,10,00,11,00,01,10,01,01,01,11,11,00,01,00,03,fe,32,"

ooharak@air ~
$ perl cro.pl AA 5A 8F 32 F5 21
"00,04,22,26,04,00,26,04,00,26,04,00,73,0c,00,34,21,00,9a,10,00,26,04,00,6c,dc,02,20,10,10,10,10,10,11,01,01,11,10,00,10,10,01,10,01,01,01,11,11,00,00,10,03,fe,32,"

この内容をSweet Memories for CROSSAM2というツールでCROSSAM2に書き出して使います。

普通にレコーダーを起動して、リモコンに登録した信号をレコーダーに送ると、以下のようなカラーバーが出れば成功です。


サービスモードへの入り方

普通のリモコンのスタートメニュー→各種設定→管理設定→システム動作テストを押すと、「アンテナ信号」「電話線接続」などの設定画面になります。この状態で先ほどカラーバーを出したリモコンの信号を送ると、以下のような「メイン検査メニュー」が現れます。

写真では見づらいですが、画面下のほうにメニューが並んでいるので「エージング」を選択してPVR検査メニュー画面を出します。実はHDDを入れ替えたときに写真を撮らなかったので、これ以降の画面のキャプチャがないのですが、PVR検査メニューで「HDD-ID登録」という項目が「不一致」であるのを選んで決定ボタンを押すと「済」に変わります。あとは画面どおりに検査メニューを終了し、電源を入れなおすことで換装は成功します。
(この項は参考サイトの掲示アーカイブの11スレッド目の526を参考にしました)

おまけ

リモコン信号解析

ここに至るまでに、ブレッドボード上で、PICマイコンと赤外線受光器と2行液晶ディスプレイで簡単な解析器を作ってみたり大変でした。(解析はうまくいったのですが、後から考えると、結論的には解析しなくてもネット上の情報だけでなんとかなりました)

リモコンの受信部は ブレッドボードではじめる マイコンプログラミング という本をほぼ参考にしました。ただし処理系をMikroC→XC8に変えたり、解析結果をLCDに表示するようにしたりし、赤外線の規格も本ではNECフォーマットというものが説明されていましたがシャープのリモコンは家電協フォーマットという別の規格なのでそれにあわせて書き換えが必要でした。ソースコードについては、この書籍に載っているものをベースにアレンジしているので、ここには載せませんが、NECフォーマットも家電協フォーマットも、タイミングの値が異なるだけで構造は似通っているので、たいした変更ではありません。





Sweet Memories for CROSSAM2の動作環境

Windows 7で動くかどうか試していませんが、なにぶん古いソフトウェアで、VBのライブラリを参照していてりするので、Windows 7 UltimateのWindows XP Modeで実行しました。そう、もうすぐ非推奨になってしまう、あれです。

私の持っているクロッサムについて言えば、シリアル接続ですので、USB-シリアル変換ケーブルを介して接続しさえすれば、原理的にはシリアル通信を行うプログラムを書けばデータの読み書きができそうです。実際、Linuxなどでクロッサムを扱うためのスクリプトなどもあるかも探せばあるのだと思われます。

クロッサムが入手できない場合、自前で赤外線LEDを制御し、信号を発出する方法があります。実は、前項に載せた手書きの回路図にあるとおり、その部分もPICでやろうとしたのですが、プログラムが悪いのか、適当な故障リモコンからはずしてきた赤外線LEDを使ったことが悪いのか、うまく動きませんでした。今回は幸いクロッサムを持っていたので事なきを得ました。

メーカーに考えてほしいこと

  • そもそも壊れやすすぎることが一番の問題ですよね…
  • HDDの換装がしにくい仕様にしているのは、ダビング10のようなDRM的な配慮か、もしくは廉価なHDDを使って大容量化されることによって上位モデルが売れなくなることを恐れたのでしょうか。私は海賊行為には反対ですが、今回のような自前の修理がしづらいことなどを考えても、コンテンツプロバイダの顔色ではなく、もう少しユーザの方に立ってほしいと思います。

Maxima 5.31.2 + TeXmacs 1.99.1 の連携がうまくいかない件の(とりあえずの)対策方法

マイ環境 is Windows7 64bit .

Maxima encountered a Lisp error:

Error in MYPRINC [or a callee]: No class named: CONDITIONS::INTERNAL-PROGRAM-ERROR.

Automatically continuing.
To enable the Lisp debugger set *debugger-hook* to nil.

いろいろ惑いましたが、結局TeXmacsのメーリングリストの以下の記事のとおりでうまくいきました。
http://lists.texmacs.org/wws/arc/texmacs-users/2014-01/msg00060.html

C:\Program Files (x86)\TeXmacs\plugins\maxima\lisp\texmacs-maxima.lisp

(defconstant texport *standard-output*)

(setq texport *standard-output*)

にするだけ。本当に何も問題ないのかはわかりませんが、今のところはこれでうまくいっています。

jBPMとか

マーケティング的な問題とか色々で名前が混乱しているがOSS版のDroolsというのが大体JBoss Enterprise BRMSである。
BPMN2ないわゆるワークフローエンジン部分がDrools FlowでありjBPM5である、といった理解。
しかしJBossとつけばエンタープライズとかそういう簡単な話ではない。

  • BPMN2のEclipseのエディタはdroolsを冠したものは古くeclipse.orgでホストされているほうが新しい。しかしいずれにしてもBPMNのフルサポートではない。
  • BPELもサポートしている的なことをどこかに書いてあったように思ったが未調査。

ESXi5.1メモ

2009年の4.0以来の実施。isoの形式が変わっている。

  • USBスティックはブータブルにするためにはMBR用に考慮が必要。単純にisoをddするだけではだめ。
  • 今回インストールしようとしたPCのNICドライバはESXiに同梱されているが、PCIで認識されたデバイスIDからそのドライバに紐付けをするためのマッピングファイルの中にそのデバイスIDが列挙されてないためにそのドライバが使われず、NIC非対応と出る。
  • ドライバはv00という拡張子の中に入っているがvmtarというツールでアーカイブされた特殊な形式になっているので、このツールで一旦ほどく必要があるがvmtarはインストール済みのESXiの中にしかない。宝箱の鍵が宝箱の中にある状態。
  • 最近のESXiはオープンソースと称してソースを公開しているらしい(がライセンスは未確認)が、数百メガバイトあったのでそれはやめ、一旦VMWare Fusion の中にESXiをインストールしたあと、その中でvmtarを実行してv00ファイルを作成することにした
  • ESXiのコンソール(Alt+F1)に入ったところnetcatが入っていたがうまく外部からアクセスされない。結局、ファイアウォールが原因。vSphere Clientでログインして(そのために.Netが必要なのは従来通り)確認すると、vMotionか何かに使える8100/tcpだかのinboundが空いているのでそこでnc -lしてうまく外部からファイルを取得できた。

HotSpotのGCメモ as of December 2012

注:Sunの資料などを読んだ自分メモです。

default GCはyoungとtenuedのgenerationを持つ。

young := eden+from+to
GC時(eden,from)は必ず空になる

EDEN FROM TO TENUED
a b c d
{GC : a不要}
b c d

MIN <= eden+from+to <= MAX
where
MIN = min(MaxNewSize, max(NewSize,heap/(NewRatio+1)))
MAX = MaxNewSize

Perm領域 ∋ Class, Method etc.

CMS ( Concurrent Mark-Sweep) aka. concurrent low pause collection

(gencon)
- TENUREDに対するGC
- 多くの処理をアプリとは並行(concurrently)に行い停止を減らす。
- 一定割合(default 68%) のTENUEDが使われると発動。

CMSの6フェーズ

1. 全スレッドを止め、根から直接到達可能なobjをマークしスレッドを再開

2. 推移的に、紐付くobjもマークしていく。(concurrent marking)

3. フェーズ2の間に変更されているobjがあるか再度スキャンする。

4. 一回stop-the-worldしてマークをやり終える。中には、この時点で不要になっているにもかかわらずマークしてしまっているのもあるが、それらは今回のGCではあきらめ次回に回すことにする。

5. 不要領域を回収する。生きてるobjは移動しない。

6. 後始末


CMSについて
  • 大メモリで、たまにであってもOldGCで時間がかかるのがイヤなとき。
  • CMSはコンパクションを行わない。

→非連続になるので、空きリストを管理するコストが発生する。

  • デフラグ的なことはやる。
  • OLDが68%を超えたか、今までのGC回数とOLDの消費速度から算出したタイミングのいずれかをトリガーとして発動する。
CMSまとめ(パラレルに比べ)
  • OldGCの時間↓
  • NewGCの時間やや↑
  • スループットやや↓
  • ヒープサイズ↑
incremental mode
  • 並行フェーズを一度に行わず少しずつ行うことで、CPU数が少ない場合に停止時間を短縮する。
CMS用途
  • 長寿命の大オブジェクト
  • 停止時間少
  • -XX:+UseConcMarkSweepGC

TLAB : thread-local Allocation Buffers

  • Parallelでもたまに長いFull GCが起こる。
  • ParallelはJDK5の -server のデフォルト

Parallel Compacting Collector

  • OLD領域には左からobjを割り当てて行くので、左側の濃度が濃い。
  • 濃いところをGCしてもコストに引き合う効果がない。
  • そこでコストが引き合うところを見定めそこから右のみについてGCを実施
  • 停止が短くすむ。
  • 多くのプロセスがCPUを共用しJVMだけがCPUを独占すべきでないような場合には不向き。
  • XX:+UserParallelOldGC
  • スレッド減らすときは -XX:ParallelGCThreads=n
      • -
振る舞いベースのParallelコレクタtuning

目標値に基づいてヒープサイズとその他のパラメタが自動的に選択される。

  • -XX:MaxGCPauseMillis=n
  • -XX:GCTimeRatio=n
  • JDK6までは String#intern はPerm領域だったが7からは一般ヒープに移された。

G1GC

羊羹的に領域を分ける

各羊羹ごとにlivelinessを算出。
要らなさげなregionのみcollectionを実施

複数の領域からどこか1つにコピーすることにより、compactionを行いつつ停止時間を減らす。

cf. CMS:compactionしない, ParallelOld:全ヒープ走査するから停止時間がかかる

前回のGCに基づいて、どのくらいGCすれば時間目標を満たすか見積もるので、
かなり正確ではあるが絶対ではない。

G1GC: 大容量(>=6GB), 停止時間短(<0.5s)

向いている場合
  • ヒープの50%以上が存命データ
  • オブジェクト割り当て/長寿命化の割合が変動大
  • 望まざる長GC/コンパクション停止がある(>0.5s)


Tiered CompilationによるサーバVM起動の高速化
プロファイリング段階で、インタプリタに加えクライアントコンパイラを使う。

NUMA 複数CPUでプロセッサごとに、ハードウェア上の理由で、速いメモリ(ローカル)とそうでないメモリ(リモート)があるアーキテクチャが存在する。
この場合、メモリを割り当てたスレッドにとって速いメモリのほうをなるべく割り付けたほうがperformanceがよい。パラレルGCの場合に -XX:+UseNUMAで指定する。

  • -Xincgc
  • -Xss スレッドスタックサイズ
  • -XX:-DisableAttachMechanism