9.1.1 OS共通の場合
OSで共通の注意事項について説明します。
-
URLClassLoaderでのクラスのローディングについて
URLClassLoader経由でjarファイルからクラスをローディングする場合,ローディング処理中にJavaVMの内部で作成されるオブジェクトが,JavaVM終了時まで削除されないことがあります。適宜,Javaアプリケーションを再起動してください。
-
メソッド長の上限について
JavaVMの仕様によって,1メソッドのバイトコードは,64キロバイト以内にする必要があります。
64キロバイトを超えると,クラスファイル生成時にエラーとなるか,またはクラスのロード時にjava.lang.LinkageError例外が発生します。
また,64キロバイト以内であっても,非常に複雑で行数が多い場合は,次のような弊害が発生することがあります。
-
GC処理の実行に非常に時間が掛かる。
-
JITコンパイルに非常に時間が掛かる。
-
JITコンパイルに非常に多くのメモリを消費する。
さらに,ローカル変数情報出力機能が有効な場合は,次の弊害も発生することがあります。
-
拡張スレッドダンプの出力に時間が掛かる。
-
スレッドスタックトレースの取得に時間が掛かる。
-
例外発生時の例外オブジェクト生成処理に時間が掛かる。
そのため,Javaソース上の1メソッドの行数は,コメントや空行を除いて,およそ500行以内にすることをお勧めします。
-
-
ファイルディスクリプタのクローズについて
java.lang.Runtime.exec(),およびjava.lang.ProcessBuilder.start()で起動した子プロセスは,Process.getInputStream,getErrorStream,またはgetOutputStreamのそれぞれのメソッドで取り出したストリームを通じてプロセス間通信をします。
親プロセスでは,これらのメソッドを使わない場合でも3つのファイルディスクリプタを消費することに注意してください。
ファイルディスクリプタをクローズするのは次の場合です。
-
Processオブジェクトのファイナライズが完了した場合
-
Process.destroy()を呼び出した場合
-
これらストリームに対して明示的にclose()メソッドを呼び出した場合
-
-
システムプロパティjava.library.pathについて
システムプロパティjava.library.pathには,ユーザのネイティブライブラリの検索パスを指定します。デフォルト値を次に示します。
- Windowsの場合
-
"<JDKインストールディレクトリ>\bin,<システムディレクトリ>,<Windowsディレクトリ>,%PATH%,カレントディレクトリ"
- Linuxの場合
-
JDK下のネイティブライブラリのディレクトリ,環境変数LD_LIBRARY_PATHの設定値,"/usr/lib64:/lib64:/lib:/usr/lib"
-
システムプロパティjava.ext.dirsについて(JDK8の場合)
システムプロパティjava.ext.dirsには,通常のアプリケーションクラスよりも優先してロードするクラスを含むjarファイルを配置するディレクトリを指定します。デフォルト値を次に示します。
/opt/Cosminexus/jdk/jre/lib/ext
-
java.net.Socket.connect()のタイムアウトについて
java.net.Socket.connect()でのソケットの接続が,OSに設定されているTCP通信のタイムアウト値によってタイムアウトすることがあります。TCP通信のタイムアウト値になると,java.net.Socket.connect()に指定したタイムアウト値よりも前でも,タイムアウト値を指定していないときでも,接続がタイムアウトします。
TCP通信のタイムアウト値でタイムアウトした場合,次の詳細メッセージを含むjava.net.ConnectException例外がスローされます。
- メッセージの内容
-
Connection timed out: connect [errno=10060, syscall=select]
TCP通信のタイムアウトについては,OSのドキュメントを参照してください。
-
クラスロードのタイミングについて
Javaでのクラスファイルのメモリへの読み込み(クラスロード処理)は,プログラムの実行中に,そのクラスが初めて必要となったタイミングで実行されます。そのため,ある処理の初回実行でクラスロードの回数が多くなると,2回目以降と比較して,処理時間が長くなることがあります。この場合,処理の実行に必要なクラスを事前にロードすることで,処理時間が改善します。
-
異なるOS間で発生する文字化けについて
文字コードのUnicodeへのマッピングは,OSによって異なることがあります。このため,次の場合に文字化けが発生することがあります。文字化けが発生する代表的な文字には,—,〜,‖,−,¢,£,¬があります。
-
UTF-8などのUnicodeのエンコーディングを使用して,異なるOS間で上記文字データを受け渡す場合
-
上記文字を含む文字列リテラルがあるソースプログラムから作成したクラスファイルを,異なるOS上でリコンパイルしないでそのまま実行する場合
-
-
Java APIで使用するファイルについて
Java APIで使用するポリシーファイルや,ログイン構成ファイルなどのコンフィグレーションファイルは,UTF-8エンコーディング方式でエンコーディングする必要があります。
-
JNI関数で文字列操作をする場合のUTF-8エンコーディングについて
JNIの場合,次の文字列操作をする関数で使用するエンコーディングは,標準UTF-8ではなく,Modified UTF-8です。
-
NewStringUTF
-
GetStringUTFLength
-
GetStringUTFChars
-
ReleaseStringUTFChars
-
GetStringUTFRegion
-
-
if文の判定でジャンプできる長さの上限について
JavaVMの仕様によって,if文の判定でジャンプできる長さは32キロバイトまでです。ジャンプ先が32キロバイトを超える場合は,java.lang.LinkageErrorとなります。
-
ファイルサイズの上限について
java.util.zip,java.util.jarパッケージでは,4ギガバイトを超えるJARファイルやZIPファイルはサポートしていません。
-
java.nio.channels.FileChannelクラスのmap,transferFrom,およびtransferToメソッドについて
mapメソッドでは,2ギガバイトを超えるファイルはサポートしていません。
また,transferFromおよびtransferToメソッドでのcount指定では,2ギガバイト以上の値はサポートしていません。
-
スレッドのスタックサイズについて
JNI関数AttachCurrentThread()などを使用して,ネイティブスレッドをJavaVMに接続する場合は,-Xssオプションの指定値よりも大きなスタックサイズのスレッドで接続してください。
-
JavaプロセスがSSL/TLS通信のクライアントとして動作する場合の注意点について
SSL/TLSを使った通信相手のプロトコルを変更した場合,通信に失敗するおそれがあります。
通信相手(サーバ)側で使用できるSSL/TLSプロトコルバージョンを変更したあと,クライアント側のJavaプロセスを再起動しないでSSL/TLSを使った通信をしようとした場合,クライアント側のJavaプロセスで例外が発生して通信に失敗するおそれがあります。
これは,既知の接続先に対して以前接続に成功したプロトコルの情報がクライアント側に残っていると,そのプロトコルバージョンでSSL/TLS通信を試みる,という挙動によるものです。
通信相手が使用できるSSL/TLSプロトコルバージョンを変更する場合は,クライアント側のJavaプロセスを再起動してください。
また,通信相手(サーバ)側で使用できるSSL/TLSプロトコルバージョンを変更したあと,クライアント側のJavaプロセスを再起動しないで通信が失敗した場合は,対象のJavaプロセスを再起動してください。