finalize() でメッセージ管理クラスみたいなあちこちから呼ばれるものを使ってはいけません

基本的に滅多に起きない問題だとは思いますが。h2database の 11/28 beta 以前なら起きるかもしれない問題。レポート済み。
org.h2.engine.Session というクラスは、Class#newInstance() でインスタンス化されて Session クラスの Factory としても動作します。このときに内部的な closed フラグは false の状態。でも Factory として作られたインスタンスは Session として動くわけではないので close 処理されないまま GC の対象になります。
で、GC で finalize() が呼ばれると、Session として動くインスタンスのためのチェックロジックに引っかかって、org.h2.message.Message というクラスを使って Error を生成して投げます。
このためタイミングによっては org.h2 の他のクラスよりも先に Finalizer スレッドで org.h2.message.Message の static 初期化子が実行されることになり、優先度の低い Finalizer スレッドが org.h2.message.Message を初期化するのを他のスレッドが待つ、という状態になります。h2 を file: で使ったアプリケーションの起動が遅いことがあればこれが原因かもね。
対応策としては h2 を初期化するより前に

Class.forName("org.h2.message.Message", true, getClass().getClassLoader())

として初期化してしまえば良い。
ということを id:ashigeru さんと一緒に調べていました。Eclipse Platform で動かすと「deadlock っぽいから止めるよ!」というログを出して 5 秒くらいで止められるのですが、そのログで気づいて調べたのです。
finalize() で Error を投げても (少なくとも Sun の java 5 では捨てられるので) 意味ないのですけれども。意味がある環境があるのでしょうか。