У меня есть объект, отвечающий за сохранение состояния JTable
на диске. Он сохраняет / загружает видимые столбцы, их размер, положение и т. Д. Несколько интересных битов из определения класса приведены ниже.
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
, когда-либо. load ()
можно вызывать из множества тем. Таймер явно является другим потоком. loadFile ()
и writeFile ()
не оставляют открытые файловые потоки - они используют надежную, хорошо протестированную и широко используемую библиотеку, которая всегда закрывает потоки с помощью попробуй ... наконец
. Иногда это терпит неудачу с исключением, например:
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
Поэтому у меня есть два вопроса:
TableSaver
. package.TableSaver.access $ 600 (TableSaver.java:34)
? Строка 34 - это строка с классом TableSaver {
. Может ли это быть причиной того, что синхронизация не работает? Google узнал, что это, похоже, специфично для Windows. Вот выдержка из Ошибка 6354433:
Это проблема платформы Windows с отображаемым в память файлом, то есть
MappedByteBuffer
. В документе Java 5.0 дляFileChannel
указано, что «буфер и сопоставление, которое он представляет, останутся действительными до тех пор, пока сам буфер не будет удален сборщиком мусора». Ошибка возникает, когда мы попытались повторно открыть хранилище файлов, а отображаемый буфер байтов не был GC. Поскольку нет методаunmap()
для отображаемого буфера байтов (см. ошибку 4724038), мы находимся во власти базовой операционной системы, когда буфер освобождается. ВызовSystem.gc()
может освободить буфер, но это не гарантируется. Проблема не возникает в Solaris; может быть связано с тем, как разделяемая память реализована в Solaris. Таким образом, обходной путь для Windows заключается в том, чтобы не использовать файл с отображением памяти для таблиц информации о транзакциях.
Какую версию Java/Windows вы используете? Есть ли у него последние обновления?
Вот две другие связанные ошибки с некоторыми полезными сведениями:
Что касается вашего второго вопроса, это просто автоматически сгенерированное имя класса внутреннего или анонимного класса.
Если предположить, что с кодом нет проблем, я видел, что это происходит, когда антивирусный сканер работает в фоновом режиме, который весело открывает файлы для сканирования их за кулисами. Если у вас есть резидентный сканер вирусов в памяти, который проверяет файлы в фоновом режиме, попробуйте отключить его или, по крайней мере, отключить его для каталога, из которого вы читаете/пишете.
Ваш код выглядит нормально. Вы уверены, что это не связано с правами доступа к файлам? Есть ли у приложения право записи в эту папку? В этот файл?
[EDIT] Похоже, что это связано с Windows, а не с Java. Запрошенная операция не может быть выполнена в файле с открытым разделом, отображаемым пользователем.