I have an object responsible for persisting JTable state to disk. 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();
                }
            }
        }
    }
}
- There only exists one instance of TableSaver, ever.
- load()can be called from many threads. 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.
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:
- How can this kind of synchronization fail? Note that I am sure there only is one instance of TableSaver.
- What is this thing in the stacktrace: package.TableSaver.access$600(TableSaver.java:34)? Line 34 is the line withclass TableSaver {. Can this be the reason why the synchronization is not working?
 
     
     
     
     
     
    