17

SOに関する他の同様の質問を調べましたが、他の問題が原因のようです。

まず、すべてのファイルハンドルを慎重に閉じたことを確認してから、ファイルlsof -p <pid of java>のリストを確認していました。

ランタイム全体を通してかなり一定ですが、定期的に次のlsofようにリストされた約10,000のエントリを取得します。

COMMAND   PID USER   FD     TYPE DEVICE  SIZE/OFF     NODE NAME
                                      ...
java    36809  smm *235r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *236r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *237r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *238r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *239r  PSXSEM              0t0          kcms00008FC901624000

マニュアルページにはPSXSEM、タイプはPOSIXセマフォであると記載されています。JDKがPOSIXセマフォを使用するための手がかりはありますか?ところで、このアプリは現時点ではシングルスレッドのコマンドラインアプリです。

潜在的に役立つ背景:Mac OS X10.7.3でJDK1.7にアップグレードした後、最初にこれに気づきました。

java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)

更新: JDK $JAVA_HOME1.6での再ポイントは、この問題の回避策のようです。

java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)

JDK 1.7の違いは何ですか?

4

3 に答える 3

7

次のコード ブロックまでたどることができました。

BufferedImage image = null;
ImageInputStream stream = null;
try {
    stream = new FileImageInputStream(file);
    image = ImageIO.read(stream);

} catch (Exception ex) {
    log.error("Image could not be read: "+file.getPath());

} finally {
    // ImageIO closes input stream unless null is returned
    // http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(javax.imageio.stream.ImageInputStream)
    if (stream != null && image == null) {
        try {
            stream.close();
        } catch (IOException ex) {
            log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
        }
    }
}

JavaDocs は、このメソッドが (他のメソッドとは異なり) ストリームを自動的に閉じると明確に述べています。実際、手動で閉じようとすると、「閉じられました」という例外がスローされます。私はこのオーバーロードを使用していましたが、他の人はとにかくそれをラップすると言っているImageInputStreamので、いくつかの作業を節約できると思いました。

通常のブロックを使用するように変更するとFileInputStream、リークが修正されます。

BufferedImage image = null;
InputStream stream = null;
try {
    stream = new FileInputStream(file);
    image = ImageIO.read(stream);

} catch (Exception ex) {
    log.error("Image could not be read: "+file);

} finally {
    if (stream != null) {
        try {
            stream.close();
        } catch (IOException ex) {
            log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
        }
    }
}

ここでは 1.6 が正常に機能したため、これは JDK 1.7 のバグのように見えます。

更新:この問題について、Oracle にバグ レポートを提出しました

于 2012-05-04T04:30:11.493 に答える
4

更新:他のユーザーが言っているように、ImageIO は 1.7.0_04 と 1.7.0_05 でセマフォをリークしていました。ユーザーjuancnとユーザーmccameyによるバグ報告は、修正済みとしてクローズ済みとしてマークされました (ありがとう!)。説明:

この修正により、macosx でのファイル ハンドラーのリークが報告されます。ImageIO.read(ImageInputStream) 経由とセマフォ経由の 2 つの方法でハンドラーをリークすることが言及されています。

最初のリークは確認していません。適切なリーダーが見つかった場合は、明示的に入力ストリームを閉じます。(少なくとも 1.7.4 では) ファイル ハンドルを解放するのに十分です。

ただし、セマフォの場合、大量のハンドルがリークします。jpeg 画像の行ごとに色変換を実行し、セマフォを作成するたびに (システムに 2 つ以上の CPU がインストールされているため)、個別の数を減らします。タスクを 1 に減らし (処理するスキャン ラインが 1 つあるため)、これによりセマフォのリンクを解除することはありません。

同じ問題が Linux システムにも存在しますが、名前付きセマフォごとに 1 つのファイル ハンドルを占有するため、程度は低くなりますが、macosx では常に新しいファイル ハンドルを占有します。

推奨される修正は、個別のタスクの数が明確になるまで、名前付きセマフォの作成を延期するだけです。そのため、画像の読み取りと単純な色変換 (ColorSpace.toRGB() など) 用のセマフォは作成しません。これに加えて、セマフォ破壊のトリガーとして pSem ポインターを使用します。

彼らのレポートでは修正がバージョン 8 にあることが示されていますが、バックポート レポートでは1.7.0_06 で修正されていることが示されています。

したがって、これが 1.7.0_04 または 05 で発生している場合は、少なくとも 1.7.0_06 に更新すると、この問題が解決されます。

于 2013-05-21T19:14:41.360 に答える
4

別の原因を見つけました。ColorSpace の toRGB() メソッドがセマフォをリークしているようです。次のコードを実行します。

import java.awt.color.ColorSpace;
public class Test
{
    public static void main(String[] args) throws Throwable {
        final ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
        for(int i = 0; i < 10000000; i++) {
            CIEXYZ.toRGB(new float[] {80f, 100, 100});
        }
    }
}

と:

java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)

システムファイルからあなたを除外します。

編集:すでにOracleにバグレポートを提出しました

于 2012-05-09T20:00:20.723 に答える