このページで解決しない高度なJavaのシステム障害はJaTSにお任せください

Trouble 14: その他の問題

14-1
java.lang.Stringなど、Java標準APIで用意されているクラスへパッチを適用したい時に、元の環境を壊すことなく実現する方法はありませんか。
14-2
JavaをインストールしたがJavaのバージョンが変わりません。
14-3
VMのcoreをdbxで確認したいがdbxでELFイメージでないと言われ確認できません。
14-4
PrintJobを使用して画面印刷を試みると、うまく印刷できない(サイズが調整できない)ことがあります。
14-5
RMIサーバオブジェクトがクライアントからのリクエスト処理中に、OutOfMemoryErrorを引き起こしてもサーバプロセスがEXITしません。
14-6
WebLogicでrmiを動かす際にWebLogicのクラスが無いと表示されます。
14-7
サーブレットを再起動せずにクラスファイルを変更する(自動ロード機能を使用する)と、JSPファイルにエラーメッセージが出力されてしまいます。
14-8
同PCで複数枚数のブラウザを開いてセッション管理を行う場合に、IE(5.0)を用いて2枚ブラウザを開き、1枚目操作→2枚目操作→1枚目でボタンによるPOST操作を行い、出力するHTMLファイルでJavaScriptのhistory.back()を使用すると、1枚目ブラウザの内容が2枚目ブラウザの内容と同じになってしまいます。
14-9
JavaScriptのsetTimeout()を使用して、一定間隔でsubmit()してdoGet()やdoPost()を呼んでも、ブラウザ表示内容が更新されません(InternetExplorer 5.0にて発生) 。
14-10
start コマンドを使用して複数の Java プログラムを起動するバッチファイルを作成しましたが、コマンドプロンプトウィンドウが複数開いてしまいます。コマンドプロンプトウィンドウを開かずに起動する方法はありますか?
14-11
propertiesファイルに2バイト文字のプロパティを記述するとjava.util.Properties.load()が失敗してしまいます。
14-12
XMLファイルをパースする際に、エラーが発生してしまいます。
14-13
IDLファイルのコメントに日本語を使用すると、idljの出力ファイルに不正なコードが出力されてしまいます。
14-14
VM HotSpotエラーメッセージのErrorIDの読み方が分かりません。
14-15
Strutsの正規表現による入力チェックにて、「&」が使えません。
14-16
JSPを表示させると、ブラウザの表示が途中で途切れることがあります。
14-17
長期稼動しているJavaプロセスでjstatが動かなくなります。
14-18
-XX:+PrintClassHistogramを指定しても、ヒストグラムが表示されません。
14-19
jstack, jmapコマンドで情報が取得できません。
14-20
オブジェクトの重複チェックに時間がかかってしまいます。


<Q14-1>java.lang.Stringなど、Java標準APIで用意されているクラスへパッチを適用したい時に、元の環境を壊すことなく実現する方法はありませんか。


<発生環境>
OS any
JDK any
Vender any
<A14-1>
以下の方法を用いれば、標準jarファイルに手を加えることなく、パッチ適用を実現することができます。
set customClass=(修正したクラスへのパス)
java -Xbootclasspath/p:%customClass%

Page Top

<Q14-2>JavaをインストールしたがJavaのバージョンが変わりません。


<発生環境>
OS Solaris
JDK ALL
Vender Sun
<A14-2>
/usr/bin/javaはシンボリックリンクであるため、インストールしただけでは書き換わりません。そのため、シンボリックリンクを切り替える必要があります。
しかし、安易に/usr/bin/javaのシンボリックリンクを切り替えるとjavac等も同様に切り替える必要があるため、効率が悪いです。/usr/javaもシンボリックリンクのため、これを切り替えればjavaもjavacも切り替わります。/usr/javaを削除し、/usrで”ln -s ./j2se java”とするのがよいでしょう。
Page Top

<Q14-3>VMのcoreをdbxで確認したいがdbxでELFイメージでないと言われ確認できません。


<発生環境>
OS Solaris
JDK ALL
Vender Sun
<A14-3>
/usr/bin/javaはシンボリックリンクであり、/usr/java/bin/javaもシンボリックリンクです。実際は以下のとおりとなっています。
  /usr/bin/java → /usr/java/bin/java → /usr/java/jre/bin/.java_wrapper
.java_wrapperはシェルであり、以下の実体をVMとして起動しています。
  /usr/java/jre/bin/sparc/native_threads/java
そのため、dbxを起動する際は以下のとおりに起動すれば情報が取得できます。
  dbx
  /usr/java/jre/bin/sparc/native_threads/java core
Page Top

<Q14-4>PrintJobを使用して画面印刷を試みると、うまく印刷できない(サイズが調整できない)ことがあります。


<発生環境>
OS Windows2000/NT
JDK JDK1.3
Vender Sun
<A14-4>
PrintJobの代わりに、PrinterJobを使用することで解決できます。
Page Top

<Q14-5>RMIサーバオブジェクトがクライアントからのリクエスト処理中に、OutOfMemoryErrorを引き起こしてもサーバプロセスがEXITしません。

しかも、オブジェクトリファレンスは引き続き参照可能で、リクエストも受け付けるが、返り値オブジェクトが正常に返ってきません。

<発生環境>
OS Solaris2.6
JDK JRE1.3
Vender Sun
<A14-5>
RMIサーバオブジェクトのRMIインタフェース実装部を全てtry節で囲み、Throwableをcatchしてエラーハンドリング(この場合はSystem.exit)するようにすることで解決できます。
Page Top

<Q14-6>WebLogicでrmiを動かす際にWebLogicのクラスが無いと表示されます。


<発生環境>
OS Windows2000
JDK JDK1.3.1
Vender Sun
<A14-6>
WebLogicのJNDIを利用する場合など、weblogic/libのjarファイルだけではなく、classes以下のクラスも利用されるので、classes以下を配置する必要があります。
Page Top

<Q14-7>サーブレットを再起動せずにクラスファイルを変更する(自動ロード機能を使用する)と、JSPファイルにエラーメッセージが出力されてしまいます。


<発生環境>
OS Solaris2.5.1
JDK Solaris_JDK_1.2.1_04
Vender Sun
<A14-7>
クラスファイル変更時にサーブレットを再起動してください。
Page Top

<Q14-8>同PCで複数枚数のブラウザを開いてセッション管理を行う場合に、IE(5.0)を用いて2枚ブラウザを開き、1枚目操作→2枚目操作→1枚目でボタンによるPOST操作を行い、出力するHTMLファイルでJavaScriptのhistory.back()を使用すると、1枚目ブラウザの内容が2枚目ブラウザの内容と同じになってしまいます。


<発生環境>
OS Solaris2.5.1
JDK Solaris_JDK_1.2.1_04
Vender Sun
<A14-8>
history.back()を使わずに、POSTされた内容を表示用JSPファイルにリダイレクトすることで解決できます。
また、表示画面をフレーム分けしたり、Window.open()で別ウィンドウを開く場合は、各画面にユニークなNameをつけておく(例:セッションIDをつける)必要があります。
Page Top

<Q14-9>JavaScriptのsetTimeout()を使用して、一定間隔でsubmit()してdoGet()やdoPost()を呼んでも、ブラウザ表示内容が更新されません(InternetExplorer 5.0にて発生) 。


<発生環境>
OS Solaris2.5.1
JDK JDK1.2.1
Vender Sun
<A14-9>
IEの「ツール」→「インターネットオプション」→「設定」→「ページを表示するごとに確認する」に設定すると、表示内容が更新されるようになります。
Page Top

<Q14-10>start コマンドを使用して複数の Java プログラムを起動するバッチファイルを作成しましたが、コマンドプロンプトウィンドウが複数開いてしまいます。コマンドプロンプトウィンドウを開かずに起動する方法はありますか?

バッチファイルの内容
start java myclass1
start java myclass2

<発生環境>
OS Windows2000/XP
JDK JDK1.4.1
Vender Sun
<A14-10>
以下のように、start コマンドの /b オプションを使用することで、新しいウィンドウを開かずにアプリケーションを実行することができます。startコマンドの詳細については Windows ヘルプを参照してください。

start /b java myclass1
start /b java myclass2

また、java コマンドの代わりに javaw コマンドを使用しても同様の効果を得ることができます。

start javaw myclass1
start javaw myclass2

javaw コマンドに関してはこちらを参照して下さい。
http://java.sun.com/j2se/1.4/ja/docs/ja/tooldocs/win32/java.html
Page Top

<Q14-11>propertiesファイルに2バイト文字のプロパティを記述するとjava.util.Properties.load()が失敗してしまいます。


<発生環境>
OS Windows2000
JDK JDK1.3
Vender Sun
<A14-11>
2-5と同様です。
Page Top

<Q14-12>XMLファイルをパースする際に、エラーが発生してしまいます。

XMLファイルから日本語を消去すると問題なく動作しました。
発生した際のエラーメッセージは以下の通りです。

文字変換エラー: "Unconvertible UTF-8 character beginning with 0x95" (行番号が小さすぎる可能性があります)

<発生環境>
OS WindowsXP
JDK JDK1.4
Vender Sun
<A14-12>
ヘッダ部で指定したエンコーディング名と、実際のXMLファイルの文字コードが異なっていないかを確認してください。
例として、XMLファイルをシフトJISで保存しているのであれば、ヘッダ部には<?xml version="1.0" encoding="Shift_JIS"?>といった指定を行う必要があります。
Page Top

<Q14-13>IDLファイルのコメントに日本語を使用すると、idljの出力ファイルに不正なコードが出力されてしまいます。

生成されたコードの中で、日本語が不明な文字コードに置き換わっています。IDLをUTF-8,SJIS,EUCなどのコードで保存しても読めないコードに変換されてしまいます。

<発生環境>
OS Windows2000
JDK JDK1.3.0_01/JDK1.4
Vender Sun
<A14-13>
idljが2バイトコードに対応していないと思われます。従って、日本語コメントの使用を避ける必要があります。
Page Top

<Q14-14>VM HotSpotエラーメッセージのErrorIDの読み方が分かりません。

VMが以下のHotSpotエラーを出しました。

# HotSpot Virtual Machine Error : 11
# Error ID : 4F530E43505002E6
# Please report this error at
# http://java.sun.com/cgi-bin/bugreport.cgi
このError IDってどういう意味なのでしょうか?
同じIDを出力することもあれば、異なる場合もあります。

<発生環境>
OS Any
JDK JDK1.4
Vender Sun
<A14-14>
Error IDはエラーが発生したJavaVMソース(※)のファイル名(のアスキーコード)+エラー発生行番号となっています。

※ JavaVMのソースコードは、Sunから無料でダウンロードすることができます。

具体的には、エラーが発生したファイル名(例えばruntime.cpp)の各キャラクタの文字コードから 0x20(空白文字のアスキーコード)を引いた値に、エラー発生行数の16進表現(2バイト)を連結した値となります。

例えば Error IDが4F530E43505002E6のときは、以下のように解釈できます。

  Error ID = 4F530E43505002E6
  ↓
  ファイル名部分=4F530E435050 + 行番号部分=02E6

  a) ファイル名部分の各値(2桁)に、0x20を加算する。
      4F 53 0E 43 50 50
    →6F 73 2E 63 70 70

  b) アスキーキャラクタ変換する。
      6F 73 2E 63 70 70
    → o  s  .  c  p  p

  c) 末尾4桁を 10進変換する。
      02E6
    →742
というわけで、os.cppの 742行目でエラーが発生したことがわかります。
Page Top

<Q14-15>Strutsの正規表現による入力チェックにて、「&」が使えません。

Strutsを利用しています。
validation.xmlのmask設定を使用して正規表現による入力チェックを行なおうとしていますが、この定義において&記号を使う事ができません。

例えば「半角英数と四則演算の記号のみ許す」という表現は

^[a-zA-Z0-9\+\-\*\/]$

で表されますが、

^[a-zA-Z0-9\+\-\*\/\&]$

などとすると、validationそのものが全く効かなくなってしまいます。
そのとき、エラーも表示されません。

<発生環境>
OS Windows XP SP1
JDK 1.4.2_05
Vender Sun
<A14-15>
"&"の代わりに"&#x26;"あるいは"&amp;"を使用してください。 XMLでは"&"、"<"は特殊な意味を持ちます。
区切り文字として使用するか、コメント、処理命令、CDATAセクション内で使 用する場合のみ、そのままの形で使用できます。
通常は、文字参照(ISO/IEC 10646 文字コード指定)あるいは文字列"&"、文 字列"<"を使用して別扱いしなければなりません。
Page Top

<Q14-16>JSPを表示させると、ブラウザの表示が途中で途切れることがあります。

Tomcatを使用しています。
JSPを表示させると、ブラウザに全てのコンテンツが表示されないまま、途中で表示が停止してしまうことがあります。

どのような原因が考えられますか?

<発生環境>
OS Windows XP SP1
JDK 1.4.2_05
Vender Sun、Tomcat4.1.x
<A14-16>
JSPコードの中で、例外が発生していないでしょうか。

アプリケーションサーバがブラウザにコンテンツを送信している最中に例外が発生すると、そこで処理が停止してしまうために、ブラウザの表示も中途半端なものになります。

通常アプリケーションサーバは、JSPコード中で例外が発生するとエラーメッセージを画面に表示しますが、ブラウザにコンテンツを送信し始めてしまった場合など、エラーメッセージを画面に表示できない場合があります。
そのような場合でもアプリケーションサーバのログにエラーが出力されている可能性があります。確認してください。

Tomcatの場合、ログのデフォルト出力ディレクトリは、
${TOMCAT_HOME}/logsです。
Page Top

<Q14-17>長期稼動しているJavaプロセスでjstatが動かなくなります。

稼働中のJavaのプロセス情報を確認するため定期的にjstatを実行しています。
長期間稼動中にjstatが"(pid) not found"と表示し、実行に失敗するようになりました。
jpsも該当のPIDを一覧化してくれません。

<発生環境>
OS Linux, (Solaris)
JDK Java SE 5.0以降
<A14-17>
jstatやjpsは、Javaプロセスが立ち上げ時に作成するhsperfdataというファイルを参照して、
Javaプロセスの存在や、Javaプロセスの情報を取得します。

このhsperfdataファイルは、Linux/Solarisでは

/tmp/hsperfdata_(ユーザ名) 以下

に保存されます。


Linuxの一部ディストリビューションでは、/tmp 以下のファイル使用量を抑えるために、
一定条件を満たすファイルを自動的に削除するように設定されています。

hsperfdataファイルがこの削除条件に該当してしまうと、
自動的に削除されてしまい、jstatやjpsはJavaプロセスを認識できなくなります。
Solarisでも同様の問題がおきる可能性があります。

Linux/Solarisでは2008/07/01時点で、/tmp 以外の場所に変更する方法はありません。

問題を回避するには以下の2つの方法があります。

 ・/tmpファイル以下の自動削除の仕組みを止める。
 ・hsperfdataファイルが削除対象にならないようにする。
    (常にhsperfdataファイルを参照するスクリプトを動かすなど)

/tmp ディレクトリの管理方法はディストリビューションによって異なるため、
使用されているディストリビューションのマニュアルを参照してください。


 この記事の詳細な情報をJTSメールマガジンにて配信しています。
 情報を取得したい方は、メールマガジンのバックナンバーを参照して下さい。

Page Top

<Q14-18>-XX:+PrintClassHistogramを指定しても、ヒストグラムが表示されません。

アプリケーションの起動時に以下のパラメータを指定し、
クラスヒストグラムを出力しようとしましたが、
クラスヒストグラムが表示されません。

-XX:+PrintClassHistogram -XX:+UseParallelOldGC

PrintClassHistogramについては、 JTSメールマガジンを参照してください。

<発生環境>
OS Any
JDK JDK5.0 update 6
Vender Sun
<A14-18>
JDK5.0では、 パラメータに -XX:+PrintClassHistogram を利用しても、
JavaのバージョンとGCアルゴリズムによっては、
PrintClassHistogramが有効にならない場合があります。

java -XX:+PrintClassHistogram -XX:+UseParallelOldGC Hello


Full thread dump Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode):

"Low Memory Detector" daemon prio=1 tid=0x08336730 nid=0x3c8a runnable [0x00000000..0x00000000]

"CompilerThread0" daemon prio=1 tid=0x08335188 nid=0x3c89 waiting on condition [0x00000000..0x00000000]

"Signal Dispatcher" daemon prio=1 tid=0x08334260 nid=0x3c88 runnable [0x00000000..0x00000000]

(中略) 

"VM Thread" prio=1 tid=0x08325fa8 nid=0x3c85 runnable

"GC task thread#0 (ParallelGC)" prio=1 tid=0x082b45c0 nid=0x3c84 runnable

"VM Periodic Task Thread" prio=1 tid=0x08337c18 nid=0x3c8b waiting on condition
この問題を解決するためには、 パラメータで指定するGCアルゴリズムを
PrintClassHistogramが使えるものに変更する必要があります。

PrintClassHistogramが使えるGCアルゴリズムは以下の通りです。

-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-Xincgc
-Xconcgc
-Xnoincgc

java -XX:+PrintClassHistogram -XX:+UseConcMarkSweepGC Hello


Full thread dump Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode, sharing):

"Low Memory Detector" daemon prio=1 tid=0x090010a8 nid=0x3dea runnable [0x00000000..0x00000000]

"CompilerThread0" daemon prio=1 tid=0x08fffb00 nid=0x3de9 waiting on condition [0x00000000..0xb227e9c8]

"Signal Dispatcher" daemon prio=1 tid=0x08ffeba0 nid=0x3de8 runnable [0x00000000..0x00000000]

(中略) 

"VM Thread" prio=1 tid=0x08ff48e8 nid=0x3de5 runnable

"VM Periodic Task Thread" prio=1 tid=0x0901be80 nid=0x3deb waiting on condition


num   #instances    #bytes  class name
--------------------------------------
  1:       163       42752  [C
  2:        13       33992  [B
  3:        29        8816  <objArrayKlassKlass>
  4:       203        7600  [Ljava.lang.Object;
  5:       156        3744  java.lang.String
  6:        41        3608  java.lang.Class

(中略)

149:         1           8  sun.net.www.protocol.file.Handler
150:         1           8  sun.reflect.ReflectionFactory
151:         1           8  java.lang.ref.Reference$Lock
152:         1           8  java.lang.Terminator$1
153:         1           8  java.util.Hashtable$EmptyEnumerator
Total    19223     1534624
なお、Java5.0以降ではJavaVMの実行環境がサーバークラスマシンとして検出されると、
自動的にGCアルゴリズムがParallelGCに変更されてしまいます。

http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/vm/server-class.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/vm/gc-ergonomics.html

この場合にもPrintClassHistogramが動作しなくなるため、注意が必要です。


参考URL:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6441368

このバグは既に修正されています。 Java5.0u10以降やJava6.0を利用することで回避できます。
Page Top

<Q14-19>jstack, jmapコマンドで情報が取得できません。

今まで稼働していたJavaプロセスが、突然操作を受け付けなくなりました。
そこで、反応しなくなったJavaプロセスの情報を取得しようとしています。

スタックトレースを表示するjstackコマンドや
ヒープ情報を表示するjmapコマンドを利用しようとしましたが
以下のように、コマンドが異常終了してしまいます。

% jstack 5535
5535: well-known file is not secure
% jstack 5535
5535: Unable to open socket file: target process not responding or 
HotSpot VM not loaded
The -F option can be used when the target process is not responding
※jmapコマンドについては、メールマガジン第4号 を参考にしてください。

<発生環境>
OS Solaris, Linux
JDK JDK6.0以降
<A14-19>
Java SE 5.0から提供されているjstackコマンド, jmapコマンドでは、
JavaVMの状態によってはコマンドが正常に動作しない場合があります。

この現象に対処するためにJava SE 6.0より
jstackコマンドやjmapコマンドに-Fオプションが追加されています。

-Fオプションを指定した場合にはJavaVMが提供する機能を利用することなく、
JavaVMの情報を取得することができます。
そのため、JavaVMが異常動作している場合にも情報取得が可能となります。


以下は、-Fオプションを利用した場合のjstackの適用例です。

% jstack -F 9813
  Attaching to process ID 9813, please wait...
  Debugger attached successfully.
  Server compiler detected.
  JVM version is 11.2-b01
  Deadlock Detection:

  No deadlocks found.

  Thread 8739: (state = BLOCKED)

  Thread 8549: (state = BLOCKED)
  (後略)

参考:
このjstackコマンド, jmapコマンドの-FオプションはJDK6u12現在では Solaris, Linuxでのみ利用可能です。
Windowsでは利用できないため、ご注意ください。


また-Fオプションを指定した場合のjstackコマンドにはいくつか制限があります。

詳細は、メールマガジン第11号を参照してください。
Page Top

<Q14-20>オブジェクトの重複チェックに時間がかかってしまいます。

処理が非常に遅くなるときがあります。
原因を調査してみたところ、containsメソッドを利用したオブジェクトの重複チェックに
時間がかかっているようです。

<発生環境>
OS Any
JDK JDK5.0以降
Vender Sun
<A14-20>
線形検索を行っている可能性が高いです。

Listのようなオブジェクトとは、containsメソッドで重複チェックを行うときに、
格納された要素を先頭から比較します。
そのため、格納している要素の数に応じて、時間がかかってしまってしまいます。


対策:
HashSetを利用して、重複チェックすることをお勧めします。

ただし、HashSetを利用する場合には、検索対象となるオブジェクトのhashCodeメソッドと、
equalsメソッドを実装する必要があるので、注意しましょう。


参考:
1万件のListとSetに対して、以下のような方法で1万回の検索を行ったところ、
それぞれ以下のような結果になりました。

List Search:828(ミリ秒)
Set Search :83(ミリ秒)

List list = search.createListData();
Set set = search.createSetData();

long start = System.currentTimeMillis();
search(list);
long end = System.currentTimeMillis();
System.out.println("List Search:"+ (end-start) + "(ミリ秒)");

start = System.currentTimeMillis();
search(set);
end = System.currentTimeMillis();
System.out.println("Set Search :"+ (end-start) + "(ミリ秒)");

/** Listデータの作成 */
public List createListData(){
  List list = new ArrayList();
  for (int num = 0; num < DATA_MAX; num++){
    list.add(String.valueOf(num));
  }
  return list;
}

/** Setデータの作成 */
public Set createSetData(){
  Set set = new HashSet();
  for (int num = 0; num < DATA_MAX; num++){
    set.add(String.valueOf(num));
  }
  return set;
}

/** containsによる重複チェック */
public void search(Collection col){
  Random random = new Random();
  for (int num = 0; num < REPEAT_TIME; num++){
    int searchData = random.nextInt(DATA_MAX);
    col.contains(String.valueOf(searchData));
 }
}
Page Top

注意:本文書の内容に誤りがあり、またこの文書によって不利益を被っても、
Acroquest Technology 株式会社は一切関知いたしません。

  • 現象別Index
  • 原因別Index

Find Bugsバグ詳細

Find Bugs Bug Descriptions日本語版

RSSで更新情報を取得する

RSSとは、ホームページの更新情報を配信する為のフォーマットです。
RSSを利用すると、登録したページの情報が更新された場合に、更新情報を自動的に受け取る事ができます。

詳細

弊社小森が執筆致しました

Javaでオブジェクト指向開発

Javaプログラミング言語習得において、新人プログラマーの最初の障害は「オブジェクト指向の壁」です。
本書は、Javaのソフトウェア開発を中心に事業を発展させてきたAcroquest社の新人教育セミナーを加筆・書籍化したもので、大卒の新人に対して、ゼロからJava言語を教えてきた実績をフィードバックしています。

メールマガジン配信中

Javaトラブルシューティングのメルマガをはじめました!是非ご購読ください

詳細