operator does not exist: integer !=- integer

久しぶりに NetBeans で開発してみようかと思って、Tomcatを起動して動かしてみたら、こんなエラーを吐いて落ちる。なんでじゃ。APサーバー上では動いているのに。

org.postgresql.util.PSQLException: ERROR: operator does not exist: integer !=- integer

コンパイルに失敗したかなーと思って、JDKを替えて再構築するも状況は変わらず。よくよくエラー部分を見ると、SQLのパースで落ちている。とは言え、「!=-」なんて意味不明な演算子なんぞ使った覚えないんですがねー。むむむ。

んで、該当のSQLを見てみると、こんな記述。

WHERE group_id!=?

どうやら PreparedStatement でパラメータに負数が入ると落ちるということらしい。そんなことあるのか。どんなパースだ。でもAPサーバーでは動いているということは、開発環境の問題なのかな。うーむ。

続きを読む "operator does not exist: integer !=- integer"

タブ区切りのソート

jmapのヒストグラムは、初めメモリ使用量の降順でプリントされる。このままだと、「残留オブジェクトの多いクラスはどれだ?」という時に困るので、オブジェクト数の降順にチャチャッとソートする方法メモ。

続きを読む "タブ区切りのソート"

jmapでオブジェクトのメモリ使用量を知る

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から使えるようになるらしいッス。

GCViewer

GCViewer

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」で良いんです。

これだけの機能があってオープンソースというのは嬉しい。

jstatの使い方

J2SE1.5から導入されたJVMの統計データ監視ツール、jstatの使い方メモ。

jstatを使えば、稼働中のJVMのヒープメモリの状態、パーマネント領域の状態、クラスローダーの統計情報などを参照することができる。イメージとしては、topコマンドみたいな感じで、JVMのリソース情報を監視できる。障害時の調査ユーティリティツールのひとつとして威力を発揮します。

まあ、プロファイリングツールではないので、メモリリークの有無は読み取れるけど、リーク箇所までは特定できないんで、そこは使い分けが必要だけど。

ここでは例として、Linuxのローカルマシン上で動いているtomcatの統計データを監視するケースを取り上げます。ただ、Windowsでも、同じ手順でOKのはず。

続きを読む "jstatの使い方"

JAVA_OPTSとCATALINA_OPTSの使い分け

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 がオプションとして付与されるようだけど、それがどう影響するのかわからない。オプションの順番で処理が変わったりするんだっけかな?

IE7対応DOCTYPEスイッチモード一覧

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へシフトする過渡期の対応ということで、個人的にはそうやっていく予定です。

IE7で再考するボックスモデルとDOCTYPEスイッチ

IE7のWeb標準準拠の動きのおかげで、DOCTYPEスイッチとボックスモデルハックを使用してきたサイトは、その設計を見直さないといけないという、やたら哀しげな状況が生まれている。まあ、自分の手がけてきたサイトがそうなんですが。

取り急ぎ、簡単な対策をメモ。

対象となるのは、XML宣言付きのXHTMLで、CSSハックによってボックスモデルを互換モードで表示しているサイト。要は、IE6を中心に設計されちゃっているサイトね。

続きを読む "IE7で再考するボックスモデルとDOCTYPEスイッチ"

とりあえずJMeterでも使ってみるか

世間は連休ということで、しばし通常業務のことは忘れて、かねてよりマスト事項だったアプリケーションの負荷試験でもやってみようかと。とりあえず、定番のJMeterを使ってみた。

JMeterについては、事前知識はほぼゼロ。「リクエストを手軽にたくさん発行できるんでしょ?」くらいのイメージだったんだけど、これがスゴイ高機能で驚いた。

  • HTTP、FTP、LDAPをはじめ、Webサービスなど多様なリクエストを測定可能
  • アサーションによるテスト結果の評価ができる
  • 分析結果は表やツリー、グラフなど様々な形態でビジュアル化
  • レスポンスをファイルに出力できる
  • テストの実行順序や実行回数の制御が可能
  • リクエストの実行間隔を制御するタイマ機能を実装している
  • リクエスト間でのパラメータの引継ぎが可能(セッションIDとか)
  • 分散クライアントによる試験が実施できる
  • HTTPプロキシ機能でテストプランの自動生成が可能
  • ユーザー定義変数を使用したパラメータの細かい制御ができる

UIの評判が悪いようだけど、思ったより直感的に操作できた。リスナーやタイマ、処理などをツリー管理するインタフェースは、オブジェクト指向的だなあ、と思った。慣れれば問題なさそう。

ただ、ちょっと触ってみた感想としては、機能がたくさんありすぎて分からない、ということ。「ユーザーパラメータ」と「HTTPユーザーパラメータ」の違いとか、よく分からない。使いこなすためには、マニュアルの精読が必須かなあ。うむむ。

まずは一度、ちゃんとシナリオを作って、一通りをやってみるのが勉強になりそう。

続きを読む "とりあえずJMeterでも使ってみるか"

DBのバイナリデータ型を読み出す方法

前回のエントリ、直列化したデータを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 を直列化する元のクラスにキャストしてあげれば、いつものように使い回せるはず。便利、便利。

直列化したデータをDBに突っ込む

シリアライズしたオブジェクトは、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に書いてあったので、多分そうなんだと思います。(おいおい)