log4jを使うとき、一般に発生する問題のリストはここにあります:
ログは、appenderを使うことによって宛先に書かれます。
appendersがカテゴリーにも、また、その先祖のうち誰にも付けられないならば、
ロギングしようとするとき、あなたは以下のメッセージを受け取るでしょう: Log4jには、デフォルトではロギング宛先がありません。
全てのカテゴリーがアペンダを受け継ぐことができるように、
確実にするのはユーザーの責任です。
これは、アペンダをrootカテゴリーに付けることによって簡単に
実現することができます。
log4j出力で重複が見られる理由は、同じアペンダを複数回同じカテゴリー
(一般的にroot)に加えたことによります、あるいは、同じアペンダをその
アペンダsを無視した異なるカテゴリーに実際加えると累積的に継承します。
log4jは、アペンダの重複を除去しません。
言い換えると、あなたが同じアペンダをcategoty にn回追加すれば、
そのアペンダは追加された宛先をn回呼び出します。 わずかに異なる原因は、若干のカテゴリーに同じ基底出力宛先を
すっかり共有している加わっている異なるアペンダです。
この現象の最も共通に発生するのは、BasicConfigurator.configure()
メソッドが複数回呼ばれた場合です。
それが呼び出されるたびに、このメソッドはrootカテゴリーに
もうひとつ他の共通の間違いは、アペンダが階層から累積的に受け継がれるのを忘れることです。
例えば、あなたがアペンダを加えるならば、rootカテゴリーにとって、
全ての他のカテゴリーは、アペンダとして
は、
値にあるスペース、すなわち
log4jのバージョン0.9.0において、全てのスペースは、オプション値の両方の後ろから削除されました。
バージョン0.9.1において、log4jはオプション値には自動的に何も手入れ
ない古い挙動に戻りました。
位置情報はPatternLayout変換パターン%C、%F、%Mと%L によって自動的に抽出されます。
しかし、いくつかのジャストインタイム(JIT)コンパイラでは、位置情報を
抽出することを不可能にします。
また、javacとjikesの-Oオプションを指定して、バイト・コードを生成した
コンパイラがLineNumberテーブルを省略したかもしれません。
あなたは、JITコンパイラを使用不能にすることによって、
そして、-Oオプションを外して、コードをコンパイルすることによってこの問題を直すことができます。
log4jがhomonymsをサポートしないので、この例外は投げられます。
例えば、以下はシステム的に
ここで
デフォルトで、 この問題に取り込むため、 当然あなたは、クラスパスをチェックするはずです。
しかし、あなたはまた、JVMで複数のclassloadersの存在を知っているはずです:
log4j.jarを サーブレット、JSP, EJBコンテナは、アプリケーションサーバーの
内部で、上記の3つのものに加えて、通常独自に指定するクラスローダーを
使用します。これはその実行時にアプリケーション・サーバと
EJBコンテナと、Webアプリケーションをべつべに分けるすばらしい機能を
提供してくれますが、初心者には頭痛のタネを提供することになります。
クラスローダーは、通常階層的な関係となります。
ブートストラップ・ローダーはその子供のために拡張ローダーとなります。
アプリケーションローダーは、拡張ローダーの子供と、その独自の
"app loader"が独立したJavaプログラムとして使用されます。
クラスを読み込む要求を受けると、クラスローダーは通常
要求を行おうとする前に、それを親に委譲します。
これは、ブートストラップと拡張ローダーにJDKやその拡張の部分によって
派生したものが取り込まれます。この委譲が失敗したときにクラスローダーは
自分自身のクラスで見つけようと試みます。クラスローダーは子供には
委譲しないことに注意してください。
アプリケーションサーバーの多くは、アプリケーションローダーを
その実行時クラスとWebアプリケーションとEJBのコンテナ用に別々に
作成します。これらの追加のクラスローダーは、直接アプリケーションサーバー
実行時のクラスローダーからdecendされるかもしれません。
もしlog4jがWebアプリケーションのクラスローダーのクラスパスに位置している
場合には、他のWebアプリケーションのクラスローダーは、見る必要はありません。
log4jがWebアプリケーションクラスローダーでクラスパスの位置に置かれるならば、
別のWebアプリケーションが必ずしもそれを見ることになるというわけでありません。
EJBも同様です。
log4jがアプリ・サーバーに参加している全てのオブジェクトへの作られた
availbleであるつもりならば、それは全てのclassloadersによって見られる
クラスローダー階層において、十分に高いクラスローダーでクラスパスに含められるはずです。
IBMのWebSphereアプリケーション・サーバーを使用した例による
クラスローダーに関する良い記事は、PDFフォーマットで
ここ
で見つけることができます。
[訳注: これは熊坂祐二が翻訳しました。
日本語訳に対するコメントは、jajakarta-report@nekoyanagi.com宛に送って下さい。]
log4jは、正しく初期化するように私に言います。
log4j: No appenders could be found for category (some.category.name).
log4j: Please initialize the log4j system properly.
log4j 出力が2重になる.
System.out
宛先を持つアペンダを加えます。
A
を受け継ぐ。と、A
が言います。
このように、あなたがA
をcategoyに加えるならば、それから、
A
がrootと一度でそうであるので、それがC
でそうであるので、
カテゴリーC
の可能にされたステートメントは二回、
一回A
に印刷します。と、C
が言います。"fruit"
キーと、"orange "
値をオプション
として戻します。"orange "
は、上で示される例のように
行末の見えないスペースのために起こります。
このように、オプションの一部は、スペースを引きずることのために正しく解釈されないかもしれません。
位置情報は、「?」文字として印刷されます。
Category
サブクラスのインスタンス化をするときに
ClassCastException
が発生します。ClassCastException
を投げます
Category c1 = Category.getInstance("bad");
MyCategory c2 = (MyCategory) MyCategory.getInstance("bad");
MyCategory
がCategory
のサブクラスです。
二回目のgetInstance
の起動が最初の起動で構築されたカテゴリーを取り出すので、問題は起こります。
このインスタンスは、Category
オブジェクトであって、
MyCategory
へのキャストであるはずではありません。PropertyConfigurator
は、
org.apache.log4j.Category
オブジェクトを作成して、設定します。
このように、あなたがすでに現存のカテゴリーのためのカテゴリーサブクラスをインスタンス化して、
サブクラスタイプにそれを投げようとしようとするならば、
あなたはシステム的にClassCastException
を得ます。PropertyConfigurator
は
log4j.categoryFactory
キーを認めます。このキーの値は
Categoryオブジェクトのインスタンス化の時にfactoryを呼び出すのに
使用されます。DOMConfigurator
は、
instantiateするカテゴリー・オブジェクトのクラスを
セットするためにより洗練された粒メソッドを持ちます。
Log4j class not found/defined
jre/lib/ext
ディレクトリに置き
ユーザ定義の拡張をアプリケーション・クラスローダーのクラスパス
にしなかったときには、log4jは見つけられません。