[英]File access synchronized on Java object
I have an object responsible for persisting JTable
state to disk. 我有一个对象负责将
JTable
状态持久化到磁盘。 It saves/loads visible columns, their size, position etc. A few interesting bits from its class definition are below. 它保存/加载可见列,它们的大小,位置等。下面是类定义中的一些有趣的部分。
class TableSaver {
Timer timer = new Timer(true);
TableSaver() {
timer.schedule(new TableSaverTimerTask(), 15000, SAVE_STATE_PERIOD);
}
synchronized TableColumns load(PersistentTable table) {
String xml = loadFile(table.getTableKey());
// parse XML, return
}
synchronized void save(String key, TableColumns value) {
try {
// Some preparations
writeFile(app.getTableConfigFileName(key), xml);
} catch (Exception e) {
// ... handle
}
}
private class TableSaverTimerTask extends TimerTask {
@Override
public void run() {
synchronized (TableSaver.this) {
Iterator<PersistentTable> iterator = queue.iterator();
while (iterator.hasNext()) {
PersistentTable table = iterator.next();
if (table.getTableKey() != null) {
save(table.getTableKey(), dumpState(table));
}
iterator.remove();
}
}
}
}
}
TableSaver
, ever. TableSaver
实例。 load()
can be called from many threads. load()
可以从许多线程调用。 Timer clearly is another thread. loadFile()
and writeFile()
do not leave open file streams - they use a robust, well tested and broadly used library which always closes the streams with try ... finally
. loadFile()
和writeFile()
不会留下打开的文件流 - 它们使用一个强大的,经过良好测试和广泛使用的库,它总是通过try ... finally
来关闭流。 Sometimes this fails with an exception like: 有时这会失败,例外情况如下:
java.lang.RuntimeException: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open)
at package.FileUtil.writeFile(FileUtil.java:33)
at package.TableSaver.save(TableSaver.java:175)
at package.TableSaver.access$600(TableSaver.java:34)
at package.TableSaver$TableSaverTimerTask.run(TableSaver.java:246)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Caused by: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at package.FileUtilWorker.writeFile(FileUtilWorker.java:57)
... 6 more
So I have two questions: 所以我有两个问题:
TableSaver
. TableSaver
实例。 package.TableSaver.access$600(TableSaver.java:34)
? package.TableSaver.access$600(TableSaver.java:34)
? Line 34 is the line with class TableSaver {
. class TableSaver {
的行。 Can this be the reason why the synchronization is not working? Google learns me that this seems to be Windows specific. 谷歌告诉我这似乎是Windows特定的。 Here's an extract of Bug 6354433 :
这是Bug 6354433的摘录 :
This is Windows platform issue with memory-mapped file, ie
MappedByteBuffer
.这是内存映射文件的Windows平台问题,即
MappedByteBuffer
。 The Java 5.0 doc forFileChannel
state that "the buffer and the mapping that it represents will remain valid until the buffer itself is garbage-collected".FileChannel
的Java 5.0 doc声明“缓冲区及其表示的映射将保持有效,直到缓冲区本身被垃圾收集”。 The error occurs when we tried to re-open the filestore and the mapped byte buffer has not been GC.当我们尝试重新打开文件存储并且映射的字节缓冲区不是GC时,会发生错误。 Since there is no
unmap()
method for mapped byte buffer (see bug 4724038), we're at the mercy of the underlying operating system on when the buffer get free up.由于映射字节缓冲区没有
unmap()
方法(参见bug 4724038),因此当缓冲区释放时,我们将受到底层操作系统的支配。 CallingSystem.gc()
might free up the buffer but it is not guarantee.调用
System.gc()
可能会释放缓冲区但不保证。 The problem doesn't occurs on Solaris;Solaris上不会出现此问题; may be due to the way shared memory is implemented on Solaris.
可能是由于Solaris上实现共享内存的方式。 So the work-around for Windows is not to use memory-mapped file for the transaction information tables.
因此,Windows的解决方法是不要将内存映射文件用于事务信息表。
What Java/Windows version are you using? 您使用的是什么Java / Windows版本? Does it have the latest updates?
它有最新的更新吗?
Here are two other related bugs with some useful insights: 以下是另外两个相关的错误,其中包含一些有用的见解:
As to your second question, that's just the autogenerated classname of an inner or anonymous class. 至于你的第二个问题,那只是内部或匿名类的自动生成的类名。
Assuming there are no issues with the code I have seen this occur when a virus scanner is running in the background which is cheerfully opening files to scan them behind the scenes. 假设我看到的代码没有问题,当病毒扫描程序在后台运行时会发生这种情况,这会快速打开文件在后台扫描它们。 If you have a memory resident virus scanner that checks files in the background try disabling it, or at least disabling it for the directory you reading from/writing to.
如果您有一个内存驻留病毒扫描程序,它在后台检查文件,请尝试禁用它,或者至少禁用它来读取/写入目录。
Your code looks fine. 你的代码看起来很好。 Are you sure it's not related to file permission?
您确定它与文件权限无关吗? Does the application has write privilege to this folder?
应用程序是否具有此文件夹的写权限? To this file?
到这个文件?
[EDIT] This seems to be Windows related, not Java The requested operation cannot be performed on a file with a user-mapped section open. [编辑]这似乎与Windows相关,而不是Java 无法在打开用户映射部分的文件上执行所请求的操作。
I had this issue with some tightly threaded Java code. 我遇到了一些带有严格线程的Java代码的问题。 I took a look at the referenced .NET conversation and the penny dropped.
我看了一下引用的.NET对话,下了便士。 It is simply that I have contention for the same file, among different threads.
简单地说,我在不同的线程中争用同一个文件。 Looking more closely the contention is ( also ) for some internals too.
对于一些内部人员来说,更密切地看待争论也是如此。 So my best course is to synchronize-d around the shared object when the update it.
所以我最好的方法是在更新共享对象时同步-d 。
This works and the error dissolves in the mist. 这有效,错误在雾中消失。
private static ShortLog tasksLog = new ShortLog( "filename" );
private static Boolean tasksLogLock = false;
...
synchronized( tasksLogLock ){
tasksLog.saveLastDatum( this.toString() );
}
see also : 另见 :
Your synchronization only protects against access from your own process. 您的同步仅防止来自您自己的进程的访问。 If you want to protect against accesses from any process, you have to use file locking:
如果要防止来自任何进程的访问,则必须使用文件锁定:
http://download.oracle.com/javase/1.4.2/docs/api/java/nio/channels/FileLock.html http://download.oracle.com/javase/1.4.2/docs/api/java/nio/channels/FileLock.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.