- PR -

WAS上のサーブレットで画像描画処理を行うとNoClassDefFoundErrorが発生します。

投稿者投稿内容
田中
会議室デビュー日: 2004/03/02
投稿数: 7
投稿日時: 2004-03-02 22:52
WebSphereをご存知でないとわからない内容ですがご容赦ください。

WebSphere5.0
RedHat Linux
という組み合わせで、サーブレット上でJPEGの描画処理を行うと
[04/02/25 23:45:05:633 JST] 712e0be4 WebGroup E SRVE0026E: [サーブレット・エラー]-[sun/awt/motif/MToolkit]: java.lang.NoClassDefFoundError: sun/awt/motif/MToolkit
というエラーが発生してしまいます。

皆様もご存知かとは思いますがsun.awt.motif.MToolkitは
/opt/WebSphere/AppServer/java/jre/lib/rt.jar
に入っていてrt.jarはWebSphereのブートストラップクラスパスに含まれています。
(SnoopServletで確認)
ですのでNoClassDefFoundErrorが発生する原因が全くわからず困っています。

その上環境変数のクラスパスにrt.jarを追加したり外したりしているうちに正常
に動く場合がありました。(現状では環境変数のクラスパスからrt.jarを外した
状態で正常に動いています。)

他のフォーラムで質問した時にはクラスローダーを勉強してくださいという指摘
をいただきました。
ですのでクラスローダーについて勉強したのですが、rt.jarはブートストラップ
クラスローダーにロードされているはずなので、warのクラスがロードされている
子供のクラスローダーからは参照可能なはずという理解しかできませんでした。
原因の解明に至る事ができませんでした。

sunのAWTの代替としてPJAも検討したのですがLinux上では一部のクラスで問題が
ありJavaVMが落ちてしまうので使用できません。

どなたかクラスローダーに詳しい方がいらしたらこの問題の原因と解決方法をご
教授ください。


ちなみに確認用のサーブレットとして以下のクラスを作成しました。
クラスをうまくロードできていない時はToolkit.getDefaultToolkit()
で落ちてしまいます。

import java.awt.Toolkit;
import java.awt.print.Printable;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @version 1.0
* @author
*/
public class TestServlet extends HttpServlet {

/**
* @see javax.servlet.http.HttpServlet#void (javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

PrintWriter writer = resp.getWriter();
writer.print(Toolkit.getDefaultToolkit());
writer.flush();
writer.close();
}


}


以上、よろしくお願いします。





koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2004-03-03 00:31
スタックトレースだけ見るとクラスパスの問題に見えますが、
Xサーバに接続しようとして失敗したのが本当の原因のような気がします。
以下のスレッドが参考になると思います。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?forum=12&topic=8200

ちなみに上記のスレッドではJ2SE1.4のヘッドレスモードを使って解決していましたが、
田中さんの場合、PJAはだめ、また、WAS5.0ということでヘッドレスモードも使えなさそうなので、
Xvfbはどうでしょうか。
田中
会議室デビュー日: 2004/03/02
投稿数: 7
投稿日時: 2004-03-03 10:45
ご返答ありがとうございます。

ご指摘いただいたように昔はXサーバーへの接続に失敗していました。
当時は以下のようなエラーが発生していました。

[04/02/25 18:46:31:547 JST] 9a36930 WebGroup E SRVE0026E: [サーブレット・エラー]-[Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.]: java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)

とほぼ同時に

[04/02/25 18:47:05:453 JST] 9a36930 WebGroup E SRVE0026E: [サーブレット・エラー]-[sun/awt/motif/MToolkit]: java.lang.NoClassDefFoundError: sun/awt/motif/MToolkit

も発生していました。
しかしその後Xサーバーへの接続の失敗は
xhost +
で解決していて発生しておりません。(セキュリティ上問題があるのですが・・)
その後はNoClassDefFoudErrorのみ出続けています。

しかし当時のログをよく見てみるとサーバーの起動直後にサーブレットにアクセスすると
[Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.]
が発生して後はいくらアクセスしても
java.lang.NoClassDefFoundError: sun/awt/motif/MToolkit
が出続けていたようです。
ですのでご指摘のようにまだXへの接続の設定で問題があるのかもしれません。
もう少しXの設定方法を調べてみます。
(ちなみにその後xhost -で接続制限を復活させてもサーブレットが正常に動くことが
あるのでなおのこと混乱しています。)

Xvfbはお客様がLinuxの運用にキャラクターログインしか許さない場合は検討してみよう
と考えています。
後は最悪の場合はAWTの使用をやめてSWTを使うことも考えています。
ただSWTを使ってもXへの接続の問題は残る可能性は高いのですが・・・・

以上、ご返答ありがとうございました。









unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-03 11:16
unibon です。こんにちわ。
#WebSphere は分かりませんが。

引用:

田中さんの書き込み (2004-03-02 22:52) より:
他のフォーラムで質問した時にはクラスローダーを勉強してくださいという指摘
をいただきました。
ですのでクラスローダーについて勉強したのですが、rt.jarはブートストラップ
クラスローダーにロードされているはずなので、warのクラスがロードされている
子供のクラスローダーからは参照可能なはずという理解しかできませんでした。


私も rt.jar にあるのだから別段のことは要らないような気もします。

NoClassDefFoundError が出るのなら、あまりたいしたことではないのですが、とりあえず
System.out.println(sun.awt.motif.MToolkit.DATA_TRANSFERER_CLASS_NAME);
みたいなことを事前にやって MToolkit クラスをロードしてみてはどうでしょうか。
なお DATA_TRANSFERER_CLASS_NAME はとりあえず目に付いた public なフィールドであり、これに拘るわけではないですが。
これでなにか挙動に変化があるかもしれません。
田中
会議室デビュー日: 2004/03/02
投稿数: 7
投稿日時: 2004-03-03 12:10
ご返答ありがとうございます。

ご指摘いただいた点なのですが恐らく
System.out.println(sun.awt.motif.MToolkit.DATA_TRANSFERER_CLASS_NAME);
を実行した時点でNoClassDefFoundErrorが発生すると思います。
私が最初の投稿時に記入させていただいたサンプルのサーブレットでは同等の処理
を行っていまして
writer.print(Toolkit.getDefaultToolkit());
は内部でsun.awt.motif.MToolkitをロードしています。
うまくいくと画面に
sun.awt.motif.MToolkit@xxxxxxx
が表示されるのですが
ロードに失敗するとNoClassDefFoundErrorが発生して落ちてしまいます。

強制的にロードさせたいのはやまやまなのですが、ブートストラップクラスローダー
がrt.jarを掴んでいるので、ブートストラップクラスローダーがロードに失敗すると
WAR内のクラスでいかにコーディングしようともロードは出来なさそうです。

先ほど実際に作業している人間から報告を受けたのですが以下の順番で作業をすると
うまくいったようです。

1.rootでRedHatにログイン
2.Xを起動
3.(xhost +などで)Xを開放
4.環境変数のクラスパスにrt.jarを追加
5.WASを起動

ただし他のマシンで同様の作業を行ったところうまくいかないことがあったとも聞きま
した。
個人的には4.の作業はいらないはずだと思うのですが担当者は必要だったと言ってい
ます。

もう少し検証してみます。

以上、ご返答ありがとうございました。


koe
大ベテラン
会議室デビュー日: 2003/07/13
投稿数: 198
投稿日時: 2004-03-03 12:59
引用:

田中さんの書き込み (2004-03-03 12:10) より:
1.rootでRedHatにログイン
2.Xを起動
3.(xhost +などで)Xを開放
4.環境変数のクラスパスにrt.jarを追加
5.WASを起動

ただし他のマシンで同様の作業を行ったところうまくいかないことがあったとも聞きま
した。
個人的には4.の作業はいらないはずだと思うのですが担当者は必要だったと言ってい
ます。


私も4.の作業は不要なように思います。これでうまくいくとのことですが、
うまくいかなかったという当初の手順はどのようになってましたか?
それと比較すると何が問題なのか見えてくると思います。

それと、Xサーバへの接続ですが、Xサーバが必要なのは最初の1回だけで、
それ以降はXサーバを落としてもAWTは動作する、という記述をどこかで
読んだ気がします。Xvfbの設定に関するどこかのページに書いてあったような…。
ただし、この話は出典を失念した上試していないので、
噂話やヨタ話レベルのものだと判断してもらってもかまいませんが
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-03 19:18
unibon です。こんにちわ。
#WebSphere に加えて、あと X window もあまり知りません。

引用:

田中さんの書き込み (2004-03-03 12:10) より:
うまくいくと画面に
sun.awt.motif.MToolkit@xxxxxxx
が表示されるのですが
ロードに失敗するとNoClassDefFoundErrorが発生して落ちてしまいます。


素朴な疑問なのですが、スタックトレースは出ないのでしょうか。WebSphere が隠しているのでしょうか。それとももともと NoClassDefFoundError のときはスタックトレースが出ないものなのでしょうか。
Java の中で NoClassDefFoundError を throw している箇所は10箇所程度しかないと思うので、どこなのかが分かればなにか手がかりになるかも、と思ったのですが。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-03 20:28
unibon です。こんにちわ。

引用:

田中さんの書き込み (2004-03-03 12:10) より:
ご指摘いただいた点なのですが恐らく
System.out.println(sun.awt.motif.MToolkit.DATA_TRANSFERER_CLASS_NAME);
を実行した時点でNoClassDefFoundErrorが発生すると思います。
私が最初の投稿時に記入させていただいたサンプルのサーブレットでは同等の処理
を行っていまして
writer.print(Toolkit.getDefaultToolkit());
は内部でsun.awt.motif.MToolkitをロードしています。


Toolkit.getDefaultToolkit のソースコードを見たところ、かなり複雑な場合分けをやっているみたいです。また、その中に Class.forName や ClassLoader が垣間見えることから考えると、sun.awt.motif.MToolkit クラスのクラス変数にアクセスしてクラスがロードされるやりかたは、少し異なるかもしれません。

スキルアップ/キャリアアップ(JOB@IT)