Trouble 13: 例外が発生します
<Q13-1>DateFormat.getDateInstance()で取得したインスタンスで日付文字列をパースしたところ、ParseExceptionが発生します。
しかし、地域(またはLANG)の設定によっては発生しないこともあります。
| <発生環境> |
| OS |
Any |
| JDK |
Any |
| Vender |
Any |
- <A13-1>
- ロケールの設定が異なると、日付文字列のパースに失敗する可能性があります。
状況によって、以下のようにする必要があると考えられます。
(特定のロケールに依存した文字列をパースする場合)
DateFormat.getDateInstance(int, Locale) など、Localeを引数に持つメソッドを使用してロケールを明示的に指定する。
(特定のフォーマットに従った文字列をパースする場合)
DateFormatのサブクラスであるSimpleDateFormatクラスに対し、フォーマット文字列を明示的に指定して使用する。ミリ秒などを含む文字列をパースする場合などが該当します。
Localeクラス、SimpleDateFormatクラスの詳細はAPIリファレンスを参照してください。
(フォーマット文字列の詳細はSimpleDateFormatクラスの説明として記述されています)
<Q13-2>RMI通信時に、jarファイルの中に該当クラスが含まれているにもかかわらず、クラスローディングに失敗し、java.rmi.UnmarshalExceptionが発生してしまいます。
RMI通信時に、jarファイルの中に該当クラスが含まれているにもかかわらず、クラスローディングに失敗し、java.rmi.UnmarshalExceptionが発生してしまいます。
| <発生環境> |
| OS |
RedHatLinux6.2 SMP |
| JDK |
JDK1.3.0 |
| Vender |
Sun |
<Q13-3>JDK1.3で動作していたプログラムをJDK1.4で実行したところ、Naming.bind()で例外が発生しました。
以下の例外が発生しました。
java.net.MalformedURLException: invalid URL string:
rmi://192.0.0.1:21000/Some Host
at java.rmi.Naming.parseURL(Naming.java:266)
at java.rmi.Naming.bind(Naming.java:104)
- 中略 -
Caused by: java.net.URISyntaxException:
Illegal character in path at index 26:
rmi://192.0.0.1:21000/Some Host
at java.net.URI$Parser.fail(URI.java:2701)
- 後略 -
| <発生環境> |
| OS |
Solaris8 |
| JDK |
JDK1.4 |
| Vender |
Sun |
<Q13-4>メモリが不足していないのに、OutOfMemoryErrorが発生します。
アプリケーションでOutOfMemoryErrorが発生しています。
jstatやhprofでメモリの使用状況を確認しましたが、特にメモリリークはしていない様です。
ソースコードにも、メモリリークを引き起こすような問題は見付かりません。
| <発生環境> |
| OS |
Any |
| JDK |
5.0 Update6 |
| Vender |
Sun |

<Q13-5>Sunが公開しているftpクラスで複数ファイルを転送しようとすると例外が発生します。
| <発生環境> |
| OS |
Linux |
| JDK |
JDK1.3 |
| Vender |
Sun |
- <A13-5>
- Sunの公開しているftpクラスが、ファイル転送後にsocketをクローズしていないのが原因です。logoff(bye)をすればsocketはクローズされるため、不具合ではなく、仕様である可能性もあります。
なお、このftpクラスはSunが参考のために公開していたクラスのため、Sunのサポート対象外となっています。
現在、この不具合(?)が直っているかどうかは不明です。
<Q13-6>MappedByteBufferを使用していると、メモリが足りなくなります。
ファイルへの高速アクセスのために、java.nio.MappedByteBufferを使用してアプリケーションを作成しています。
必要な時にMappedByteBufferを初期化し、不要になった時点でcloseしていますが、実行中に以下の例外が発生してしまいます。
java.io.IOException: このコマンドを実行するのに十分な記憶域がありません。
at sun.nio.ch.FileChannelImpl.map0(Native Method)
at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:742)
at mappedbytebuffer.TestMemoryMapping.main(TestMemoryMapping.java:22)
どんな原因が考えられますか?
| <発生環境> |
| OS |
Windows XP SP2 |
| JDK |
5.0 Update4 |
| Vender |
Sun |
- <A13-6>
- MappedByteBufferを使用すると、JavaVMプロセスのアドレス空間中に連続したメモリ領域を確保します。
このメモリの確保に失敗すると、Qの例外が発生します。
MappedByteBufferは、ガベージコレクトされるまで確保したメモリ領域を解放しない仕様になっています。
つまり、仮にバッファをcloseしたとしても、その時点ではメモリ領域の解放は行われません。
ガベージコレクトが実行されればメモリ領域は解放されますが、MappedByteBufferの使用するメモリ領域は通常のJavaオブジェクトとは別の所に確保されるので、ガベージコレクトの契機にはならない場合があります。
その結果、Javaオブジェクトを保存するメモリ領域(heap)は十分でも、MappedByteBufferの使用するメモリ領域が不十分になり、Qの例外が発生することがあります。
MappedByteBufferを使用するのは、システム終了までリソースを解放しなくても良い場合に限るべきです。
例えば、システムで使用する大量のデータを、リングバッファとして保持する場合に使用するなどはMappedByteBufferの好例でしょう。
<Q13-7>Tomcat5上でcommons-loggingを使ったウェブアプリケーションのデプロイが例外発生して失敗してしまいます。
Tomcat5上でcommons-loggingを使ったウェブアプリケーションを読み込むとNullPointerExceptionが発生してデプロイ終了してしまう場合があります。
| <発生環境> |
| JDK |
1.5.0 |
| Tomcat |
5.5 |
- <A13-7>
- これはcommons-loggingのVersion 1.1を利用している場合に発生する問題です。
commons-loggingのClass Loaderの問題で発生します。
これを回避するためには、commons.loggingのVersionを1.0.4に変更する必要があります。
参考URL:
https://issues.apache.org/bugzilla/show_bug.cgi?id=39631
参考)
以下のエラーメッセージは、commons.loggingとLog4jをTomcatで利用した場合の
スタックトーレスの出力例です。
java.lang.NullPointerException
at org.apache.log4j.Category.isEnabledFor(Category.java:746)
at org.apache.commons.logging.impl.Log4JLogger.isTraceEnabled
(Log4JLogger.java:327)
at org.apache.catalina.startup.TldConfig.tldScanResourcePaths
(TldConfig.java:581)
==== 以下省略 ====
注意:本文書の内容に誤りがあり、またこの文書によって不利益を被っても、
エスエムジー株式会社は一切関知いたしません。