2

ディレクトリツリーの変更を監視する必要のあるJavaプログラムがあります。を使用するJNIコードがありますReadDirectoryChangesW()。ディレクトリは次のように開かれます。

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

そして、私はに渡しdirHandleますReadDirectoryChangesW()。それはすべてうまく機能します。

問題は、コードの他の部分(Java側)がFile.setLastModified()ファイルまたはディレクトリに「タッチ」するために使用することです(タイムスタンプを「今」に更新します)。これは一般的に機能します。ただし、を使用して開いたディレクトリに「タッチ」しようとすると失敗しますCreateFile()

実際に発生しているWindowsエラーを確認するために、JDKソースを調べて、File.setLastModified()エラーを出力することを追加して、独自のコードで再実装しましたGetLastError()。エラーは次のとおりです。

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF?同じプロセスです。私も合格FILE_SHARE_READFILE_SHARE_WRITEましたCreateFile()

これを機能させる方法はありますか?

より詳しい情報

File.setLastModified()JDKでのネイティブコードの実装は次のことを行います。

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

0最初のをに変更するとFILE_SHARE_READ | FILE_SHARE_WRITE、すべて機能します。したがって、JDKの実装は少し壊れているようです。:(

したがって、私の質問は次のようになります。私自身の(再)実装を使用せずにこの作業を行う方法はありFile.setLastModified()ますか?

4

1 に答える 1

1

この場合、エラーメッセージは少し誤解を招く可能性がありますが、表示されるのは通常の動作です。

ゼロに設定されたディレクトリを開くことによりdwShareMode、JDKは事実上、排他的アクセスを要求します。これにより、他のアクセス試行が共有違反エラーで失敗します。これは、他のプロセスからのアクセスと独自のプロセス内からのアクセスに等しく適用されます。

CreateFileドキュメントdwShareModeでは、パラメータについて説明しています。

このパラメーターがゼロでCreateFileが成功した場合、ファイルまたはデバイスを共有することはできず、ファイルまたはデバイスへのハンドルが閉じられるまで再度開くことはできません。

ハンドルが開いている既存のリクエストで指定されているアクセスモードと競合する共有モードをリクエストすることはできません。CreateFile失敗し、GetLastError関数はを返しERROR_SHARING_VIOLATIONます。

したがって、あなたはあなた自身の質問に答えたようです:ディレクトリにアクセスするときにsetLastModified指定するカスタム関数が必要です。FILE_SHARE_READ | FILE_SHARE_WRITE

于 2009-07-18T10:51:33.090 に答える