久しぶりに NetBeans で開発してみようかと思って、Tomcatを起動して動かしてみたら、こんなエラーを吐いて落ちる。なんでじゃ。APサーバー上では動いているのに。
org.postgresql.util.PSQLException: ERROR: operator does not exist: integer !=- integer
コンパイルに失敗したかなーと思って、JDKを替えて再構築するも状況は変わらず。よくよくエラー部分を見ると、SQLのパースで落ちている。とは言え、「!=-」なんて意味不明な演算子なんぞ使った覚えないんですがねー。むむむ。
んで、該当のSQLを見てみると、こんな記述。
WHERE group_id!=?
どうやら PreparedStatement でパラメータに負数が入ると落ちるということらしい。そんなことあるのか。どんなパースだ。でもAPサーバーでは動いているということは、開発環境の問題なのかな。うーむ。
Posted by dT by 12:59 | Comments (0) | TrackBacks (0)
jmapのヒストグラムは、初めメモリ使用量の降順でプリントされる。このままだと、「残留オブジェクトの多いクラスはどれだ?」という時に困るので、オブジェクト数の降順にチャチャッとソートする方法メモ。
Posted by dT by 14:30 | Comments (0) | TrackBacks (0)
J2SE1.5から試験導入されたトラブルシューティングツールのひとつ、jmapを使用するとヒープダンプ情報を取得することができる。どのオブジェクトが今どのくらい生成されて、どのくらいのサイズを占有しているか、定量的に見ることができる優れもの。これがJDK標準装備というのは素敵ですよ、奥さん。
とりあえず、一番わかりやすいところで、ヒープのヒストグラムを表示。
# jps 497 Jps 19719 Bootstrap
# jmap -histo 19719 > heap_histo.txt
すると、「heap_histo.txt」にメモリの現状がどわーっと表示されます。
Object Histogram: Size Count Class description ------------------------------------------------------- 65156376 461687 char[] 22587104 118976 * ConstMethodKlass 19391400 484785 java.lang.String 14393048 11237 * ConstantPoolKlass 12386464 118976 * MethodKlass 10034000 102739 java.lang.Object[]
どのクラスのオブジェクトがどれくらいメモリを食っているかを知りたい場合にも良いし、メモリリーク時の原因調査の足がかりとしても使えそう。まあ、メモリリーク対策をするなら NetBeans とかのプロファイラーを使った方が良いんだけど、実運用環境で使えるという点では jmap は有用じゃないかと。
ただし、1.5ではSolaris/LinuxのJDKのみ。Windowsでは6から使えるようになるらしいッス。
Posted by dT by 23:08 | Comments (0) | TrackBacks (0)
JVMが吐き出すガーベッジコレクションのログを視覚化するツール。WindowsでもLinuxでも使える。稼働中のGCログを監視して、ダイナミックにグラフ化することもできるので、チューニング時に重宝するツールというわけです。
使い方は、いたってシンプル。JVMの起動時に、以下のようにGCログの出力先を指定して、そのログファイルを噛ませるだけ。ちなみに、これはSunのJVMの場合。HP-UX JVMとかは、-XVerbosegcとかで行けます。まあ、HP-UXだったら、HPjtuneを使った方が良いけど。
java -Xloggc:/var/log/gc.log -XX:+PrintGCDetails
「+XX:+PrintGCDetails」を指定することで、Young領域とOld領域の情報もグラフに表示できるようになる。まあ、男は黙って「+XX:+PrintGCDetails」で良いんです。
これだけの機能があってオープンソースというのは嬉しい。
Posted by dT by 18:12 | Comments (0) | TrackBacks (0)
J2SE1.5から導入されたJVMの統計データ監視ツール、jstatの使い方メモ。
jstatを使えば、稼働中のJVMのヒープメモリの状態、パーマネント領域の状態、クラスローダーの統計情報などを参照することができる。イメージとしては、topコマンドみたいな感じで、JVMのリソース情報を監視できる。障害時の調査ユーティリティツールのひとつとして威力を発揮します。
まあ、プロファイリングツールではないので、メモリリークの有無は読み取れるけど、リーク箇所までは特定できないんで、そこは使い分けが必要だけど。
ここでは例として、Linuxのローカルマシン上で動いているtomcatの統計データを監視するケースを取り上げます。ただ、Windowsでも、同じ手順でOKのはず。
Posted by dT by 12:22 | Comments (0) | TrackBacks (0)
tomcat起動時にJVMのオプションを指定するために、JAVA_OPTSとCATALINA_OPTSという2つの環境変数が用意されている。何が違うんだろうと思って、catalina.shを開いてみたら、両方に同じ説明が書いてある。
# CATALINA_OPTS (Optional) Java runtime options used when the "start", # "stop", or "run" command is executed. # # JAVA_OPTS (Optional) Java runtime options used when the "start", # "stop", or "run" command is executed.
評価としては、JAVA_OPTS の次に CATALINA_OPTS がオプションとして付与されるようだけど、それがどう影響するのかわからない。オプションの順番で処理が変わったりするんだっけかな?
Posted by dT by 19:12 | Comments (0) | TrackBacks (0)
IE7(RC1)のDOCTYPEスイッチ対応を調べる過程で出来あがった、DOCTYPE宣言による各UAの標準・互換モード切替状況の一覧表をさらしておきます。間違いがあれば、ご指摘くだされ。>誰
| 文書型 | IE7 | IE6 | MacIE5 | Gecko系 | Opera |
|---|---|---|---|---|---|
| なし | 互換 | 互換 | 互換 | 互換 | 互換 |
| HTML4.01 Strict (URL無) | 標準 | 標準 | 互換 | 標準 | 標準 |
| HTML4.01 Strict (URL有) | 標準 | 標準 | 標準 | 標準 | 標準 |
| HTML4.01 Transitional(URL無) | 互換 | 互換 | 互換 | 互換 | 標準 |
| HTML4.01 Transitional(URL有) | 標準 | 標準 | 標準 | 標準 | 標準 |
| XHTML1.0 (XML宣言有) | 標準 | 互換 | 標準 | 標準 | 標準 |
| XHTML1.0 (XML宣言無) | 標準 | 標準 | 標準 | 標準 | 標準 |
XHTMLでXML宣言を書くかどうかのところで、IE7はそれ以前のバージョンと表示が変わってくるということですよ、奥さん。せっかくのXHTMLなんだから、XML宣言は欠かせないと思うので、結局はIE6以前のためにCSSハックをするような感じになるんでしょうか。IE7へシフトする過渡期の対応ということで、個人的にはそうやっていく予定です。
Posted by dT by 10:35 | Comments (0) | TrackBacks (0)
IE7のWeb標準準拠の動きのおかげで、DOCTYPEスイッチとボックスモデルハックを使用してきたサイトは、その設計を見直さないといけないという、やたら哀しげな状況が生まれている。まあ、自分の手がけてきたサイトがそうなんですが。
取り急ぎ、簡単な対策をメモ。
対象となるのは、XML宣言付きのXHTMLで、CSSハックによってボックスモデルを互換モードで表示しているサイト。要は、IE6を中心に設計されちゃっているサイトね。
Posted by dT by 12:21 | Comments (0) | TrackBacks (0)
世間は連休ということで、しばし通常業務のことは忘れて、かねてよりマスト事項だったアプリケーションの負荷試験でもやってみようかと。とりあえず、定番のJMeterを使ってみた。
JMeterについては、事前知識はほぼゼロ。「リクエストを手軽にたくさん発行できるんでしょ?」くらいのイメージだったんだけど、これがスゴイ高機能で驚いた。
UIの評判が悪いようだけど、思ったより直感的に操作できた。リスナーやタイマ、処理などをツリー管理するインタフェースは、オブジェクト指向的だなあ、と思った。慣れれば問題なさそう。
ただ、ちょっと触ってみた感想としては、機能がたくさんありすぎて分からない、ということ。「ユーザーパラメータ」と「HTTPユーザーパラメータ」の違いとか、よく分からない。使いこなすためには、マニュアルの精読が必須かなあ。うむむ。
まずは一度、ちゃんとシナリオを作って、一通りをやってみるのが勉強になりそう。
Posted by dT by 18:57 | Comments (0) | TrackBacks (0)
前回のエントリ、直列化したデータをDBに突っ込むの続き。DBに保存したら、読み出す方法が分からないとダメだわな。ごめんなさい。
Object object = null; InputStream in; ObjectInputStream ois;
if (resultSet.next()) { // バイナリデータを読み出して復元 in = resultSet.getBinaryStream("analyze_data"); ois = new ObjectInputStream(in); object = ois.readObject(); }
あとは、この object を直列化する元のクラスにキャストしてあげれば、いつものように使い回せるはず。便利、便利。
Posted by dT by 22:51 | Comments (0) | TrackBacks (0)
シリアライズしたオブジェクトは、DBのバイナリデータ型のカラムに登録することができる。生成にコストがかかって、かつセッションに保持するとメモリを食い潰しそうなオブジェクトの保存方法のひとつとして、この手段を検討したい。
Connection conn = null; PreparedStatement ps = null;
// 指定オブジェクトを直列化 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject((Serializable) contents); int buffer = baos.size();
// DBへの書き出し用ストリームの作成 InputStream in = new ByteArrayInputStream(baos.toByteArray());
// 直列化したオブジェクトを InputStream に書出 baos.flush();
try { String sql = "INSERT INTO table(contents) VALUES (?)"; conn = getConnection(); ps = conn.parepareStatement(sql); ps.setBinaryStream(1, in, buffer); ps.executeUpdate } catch (Exception e) { e.printStackTrace(); } finally { if (ps != null) ps.close(); if (conn != null) conn.close(); }
サンプルとしてざっくり書いてみたけど、こんな感じで大丈夫のはず。とりあえずメモなんで、動かしてないです。間違いあったら、すんません。
ちなみに、ByteArrayOutputStream の close には意味が無いらしい。転送先にデータを書き出すためには、明示的に flush する必要があるとのこと。標準APIのjavadocに書いてあったので、多分そうなんだと思います。(おいおい)
Posted by dT by 19:35 | Comments (0) | TrackBacks (0)