2

Jetty でデプロイされた Java Web アプリケーション (Spring を使用) があります。Windows マシンで実行しようとすると、すべてが期待どおりに機能しますが、Linux マシンで同じコードを実行しようとすると、次のように失敗します。

【通常起動時出力】
11:16:39.657 INFO [main] org.mortbay.jetty.servlet.ServletHandler$Context.log>(ServletHandler.java:1145) >16> Web アプリのルート システム プロパティを設定: 'webapp.root' = [/path/へ/ワーキング/ディレクトリ]
java.lang.reflect.InvocationTargetException
        sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブメソッド)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) で
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) で
        java.lang.reflect.Method.invoke(Method.java:597) で
        org.mortbay.start.Main.invokeMain(Main.java:151) で
        org.mortbay.start.Main.start(Main.java:476) で
        org.mortbay.start.Main.main(Main.java:94) で
原因: java.lang.ExceptionInInitializerError
        org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:129) で
        org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:51) で
        org.mortbay.jetty.servlet.WebApplicationContext.doStart(WebApplicationContext.java:495) で
        org.mortbay.util.Container.start(Container.java:72) で
        org.mortbay.http.HttpServer.doStart(HttpServer.java:708) で
        org.mortbay.util.Container.start(Container.java:72) で
        org.mortbay.jetty.Server.main (Server.java:460) で
        ... 7 つ以上
原因: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: 適切なログ コンストラクターがありません [Ljava.lang.Class;@15311bd for org.apache.commons.logging.impl.Log4JLogger (Caused java.lang.NoClassDefFoundError による: org/apache/log4j/Category) (org.apache.commons.logging.LogConfigurationException: 適切なログ コンストラクター [Ljava.lang.Class;@15311bd for org.apache.commons.logging. impl.Log4JLogger (java.lang.NoClassDefFoundError: org/apache/log4j/Category が原因)
        org.apache.commons.logging.impl.LogFactoryImpl.newInstance (LogFactoryImpl.java:543) で
        org.apache.commons.logging.impl.LogFactoryImpl.getInstance (LogFactoryImpl.java:235) で
        org.apache.commons.logging.impl.LogFactoryImpl.getInstance (LogFactoryImpl.java:209) で
        org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351) で
        org.springframework.util.SystemPropertyUtils.(SystemPropertyUtils.java:42) で
        ... 14以上
原因: org.apache.commons.logging.LogConfigurationException: 適切なログ コンストラクターがありません [Ljava.lang.Class;@15311bd for org.apache.commons.logging.impl.Log4JLogger (java.lang.NoClassDefFoundError が原因: org/apache /log4j/カテゴリ)
        org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor (LogFactoryImpl.java:413) で
        org.apache.commons.logging.impl.LogFactoryImpl.newInstance (LogFactoryImpl.java:529) で
        ... 18以上
原因: java.lang.NoClassDefFoundError: org/apache/log4j/Category
        java.lang.Class.getDeclaredConstructors0(ネイティブメソッド)で
        java.lang.Class.privateGetDeclaredConstructors (Class.java:2389) で
        java.lang.Class.getConstructor0 (Class.java:2699) で
        java.lang.Class.getConstructor (Class.java:1657) で
        org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor (LogFactoryImpl.java:410) で
        ... 19件以上
原因: java.lang.ClassNotFoundException: org.apache.log4j.Category
        java.net.URLClassLoader$1.run(URLClassLoader.java:200) で
        java.security.AccessController.doPrivileged(ネイティブメソッド)で
        java.net.URLClassLoader.findClass(URLClassLoader.java:188) で
        java.lang.ClassLoader.loadClass(ClassLoader.java:307) で
        java.lang.ClassLoader.loadClass(ClassLoader.java:252) で
        java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)で
        ... 24以上
【シャットダウン出力】

でアプリを実行しました。java -verbose:classその出力によると、最初の例外がスローされる直前に、/WEB-INF/lib の log4j JAR から org.apache.log4j.Category がロードされます。

現在、2 つのマシンの Java バージョンはわずかに異なります。どちらのマシンにも Sun の Java があり、Linux マシンには 1.6.0_10 があり、Windows マシンには 1.6.0_08 か、または 07 または 06 があります。正確な番号は今思い出せず、手元にマシンがありません。 . しかし、Java のマイナー バージョンがわずかに異なっていても、コードがこのように壊れることはありません。誰かがここで何が悪いのか理解していますか?

4

6 に答える 6

5

クラスローダはすべてを見ることができないことを理解する必要があります。親クラスローダーがロードしたもの、または自分自身がロードしたものしか見ることができません。たとえば、Jetty 用と Web アプリ用の 2 つのクラスローダーがある場合、Web アプリは log4j を参照できますが (JAR は WEB-INF/lib であるため)、Jetty のクラスローダーは参照できません。

log4j を使用するが Jetty のコンテキスト (およびクラスローダー) で実行されるクラス (たとえば、DB レイヤー内の何か) を Jetty で使用できるように管理すると、エラーが発生します。

これをデバッグするには、org.springframework.web.util.Log4jWebConfigurer.initLogging() にブレークポイントを設定します。可能であれば、このクラスのソースをプロジェクトにコピーし (後で削除することを忘れないでください)、次の行を追加します。

ClassLoader cl = Thread.currentThread().getContextClassLoader();

デバッガーで cl オブジェクトを見てください。これにより、作成者の情報が得られるはずです。私の推測では、これは Jetty のクラスローダーです。

[編集] 両方のクラスローダに log4j がある場合、別の混乱が生じることに注意してください。この場合、割り当て互換性のないオブジェクトを作成する同じ名前の2 つのクラスがあります。したがって、この jar のインスタンスが 1 つだけであることを確認するか、log4j のインスタンスが 2 つのコンテキスト間で渡されないようにしてください (通常は不可能です)。

于 2009-02-06T11:05:24.493 に答える
1

これは、古典的なクラスローダーの問題のようです。これは、log4j を使用する別の Web アプリが最初に読み込まれていることが原因である可能性がありますが、テストしているアプリで使用されているバージョンとは異なります。クラスローダは、検出したクラスの最初のバージョンを使用します。通常、サーバー クラスのロード ポリシーは構成ファイルで変更できます。申し訳ありませんが、これについては少しさびていますが、正しい方向に向けることができるかもしれません.

  1. Web サーバーに他のアプリがインストールされていないことを確認してください。
  2. ロードされている log4j が正しいバージョンであることを確認してください。
  3. サーバーのクラスパスのどこかにlog4jが潜んでいないことを確認してください。

HTH

于 2009-02-06T11:00:16.203 に答える
0

同じ問題があり、簡単な解決策/回避策が見つかりました:

Eclipse の [Preferences] > [Java] > [Installed JREs] で、[JRE] > [Edit and Add External JARs...] を選択し、log4j.jar を参照します。

もう 1 つの回避策は、log4j.jar を [クラスパス] タブのすべての起動定義に追加することです。

于 2011-11-28T17:01:58.110 に答える
0

両方のマシンで同じ WAR を使用していますか? WAR ファイルが同一であるか (転送エラーが発生していないか) を確認しましたか?

于 2009-02-06T10:50:54.473 に答える
0

考慮すべきいくつかのランダムなこと:

(1) web-app ディレクトリの外で、Linux インスタンス上に他のバージョンの log4j が浮かんでいるかどうかを確認しますか?

(2) apache commons ロギングはまったく使用されていますか? 代わりにSLF4Jを検討してみてはいかがでしょうか?

(3) JAR/WAR は何らかの形で破損しましたか? ASCII またはバイナリで FTP されましたか?

(4) それぞれの場合のクラスローダ階層を出力して、矛盾がないか確認しますか?

于 2009-02-06T10:57:39.733 に答える
0

元の問題は質問者のために解決されましたが、Windows と Linux (または Unix) で同じコードを実行するときの問題の一般的な原因は、大文字と小文字の区別の問題であることを指摘します。Windows では大文字と小文字が区別されますが、Linux または Unix では大文字と小文字が区別されます。これは私を何度も噛んだ。

そのため、クラスパスで jar またはディレクトリを指定しても、それが正しくない場合、Linux では失敗しますが、Windows では成功します。これは、FileNotFoundExceptions の原因になることもあります。

于 2009-04-24T07:06:05.357 に答える