JVM Tutorials - Herong's Tutorial Examples - Version 4.23, by Dr. Herong Yang
FileEditor2.java - Avoiding FileNotFoundException
This section describes a revised thread productivity testing program, FileEditor2.java, that repeats a work unit of reading data from a file and write it back to a different file to avoid the FileNotFoundException bug.
When searching for answer on the "java.io.FileNotFoundException: FileEditor.dat (The requested operation cannot be performed on a file with a user-mapped section open)" issue, I saw reports saying that it is related a known HotSpot JVM bug opened in 2002. Here is the summary of the bug:
DK-4724038 : (fs) Add unmap method to MappedByteBuffer Details Type: Enhancement Submit Date: 2002-07-31 Status: Open Updated Date: 2013-11-20 Project Name: JDK Resolved Date: Component: core-libs OS: windows_vista,solaris_8,generic,windows_2000 Sub-Component: java.nio CPU: x86,generic Priority: P4 Resolution: Unresolved Affected Versions: 1.4.0,5.0,7 Targeted Versions: ... Description Name: nt126004 Date: 07/31/2002 FULL PRODUCT VERSION : java version "1.4.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92) Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode) FULL OPERATING SYSTEM VERSION : Microsoft Windows 2000 [Version 5.00.2195] A DESCRIPTION OF THE PROBLEM : Once a file has been mapped a number of operations on that file will fail until the mapping has been released (e.g. delete, truncating to a size less than the mapped area). However the programmer can't control accurately the time at which the unmapping takes place --- typically it depends on the processing of finalization or a PhantomReference queue. The danger associated with unmapping that is noted in the JavaDoc could be avoided if when an area is unmapped, the memory is not made available for reallocation but instead is reserved (e.g. by using VirtualAlloc under Windows). Then any unwanted reference to the previously mapped area would result in an exception without incurring performance penalties. The finalization process could release the reservation when there were no remaining references to the buffer. ...
As we can see from the bug document, the bug was opened in 2002, and remained open until today. I am not sure why Sun and Oracle can not fix the issue.
So, to avoid this issue, I revised my thread class to FileEditor2.java, which reads data from a file and write it back to different file repeatedly:
/* FileEditor2.java * Avoiding using the same file repeatedly * Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ import java.io.*; import java.util.*; public class FileEditor2 extends Thread { public int fileSize; // The size of the file to work on public String fileName; // The name of the file public long jobCount; // The number of jobs done so far public int myCheckSum; // The checksum of the file public int firstByte; // The first byte of the file public long seqID; // A sequence ID public static void main(String[] a) { int size = 1000; String name = "FileEditor.dat"; long interval = 1; // Monitoring interval in seconds if (a.length>0) size = Integer.parseInt(a[0]); if (a.length>1) name = a[1]; System.out.println("File size: "+size); // Initializing the data file byte[] data = new byte[size]; Random r = new Random(); r.nextBytes(data); try { FileOutputStream fos = new FileOutputStream(name); fos.write(data); fos.close(); } catch (Exception e) { e.printStackTrace(); return; } FileEditor2 t = new FileEditor2(size, name); t.start(); int i = 0; long startTime = System.currentTimeMillis(); System.out.println( "Time, Count, Productivity, CheckSum, firstByte"); while (true) { try { sleep(interval*1000); } catch (InterruptedException e) { System.out.println("Monitor interrupted."); } long curTime = System.currentTimeMillis(); long duration = (curTime - startTime)/1000; long productivity = t.jobCount/duration; System.out.println(duration+", "+t.jobCount +", "+productivity+", "+t.myCheckSum+", "+t.firstByte); } } public FileEditor2(int size, String name) { fileSize = size; fileName = name; jobCount = 0; myCheckSum = 0; firstByte = 0; seqID = 0; } private long nextSeqID() { seqID++; return seqID; } public void run() { byte[] buffer = new byte[fileSize]; String oldName = fileName; String newName = fileName+"_"+nextSeqID(); try { while (true) { FileInputStream fis = new FileInputStream(oldName); int bytes = fis.read(buffer); fis.close(); long sum = 0; for (int i=0; i<fileSize; i++) { sum = (sum+(buffer[i]&0x00FF))%Integer.MAX_VALUE; } myCheckSum = (int)sum; firstByte = buffer[0]&0x00FF; FileOutputStream fos = new FileOutputStream(newName); fos.write(buffer,1,fileSize-1); fos.write(buffer,0,1); fos.close(); (new File(oldName)).delete(); oldName = newName; newName = fileName+"_"+nextSeqID(); jobCount++; } } catch (Exception e) { e.printStackTrace(); return; } } }
Run it with a file size of 4 to verify its correctness:
C:\>"\Program Files\java\jdk1.7.0_45\bin\javac" FileEditor2.java C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" FileEditor2 4 File size: 4 Time, Count, Productivity, CheckSum, firstByte 1, 1219, 1219, 288, 12 2, 2422, 1211, 288, 81 3, 3713, 1237, 288, 3 4, 4898, 1224, 288, 81 5, 6214, 1242, 288, 81 6, 7459, 1243, 288, 12 7, 8330, 1190, 288, 81 8, 9332, 1166, 288, 192 9, 10676, 1186, 288, 192 10, 11975, 1197, 288, 12 ...
Now try it with a file size of 10 for a long time to see if we are still getting that exceptions:
C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" FileEditor2 10 File size: 10 Time, Count, Productivity, CheckSum, firstByte 1, 1219, 1219, 288, 12 ... 156, 135524, 868, 1178, 10 157, 136251, 867, 1178, 120 158, 137176, 868, 1178, 43 159, 138112, 868, 1178, 202 160, 139069, 869, 1178, 163 161, 139834, 868, 1178, 18 162, 140802, 869, 1178, 202
Okay, looks like as have avoided the FileNotFoundException bug.
Last update: 2014.
Table of Contents
Downloading and Installing JDK 1.8.0 on Windows
Downloading and Installing JDK 1.7.0 on Windows
java.lang.Runtime Class - The JVM Instance
java.lang.System Class - The Operating System
ClassLoader Class - Class Loaders
Class Class - Class Reflections
JRockit JVM 28.2.7 by Oracle Corporation
Memory Management and Garbage Collectors
JVM Stack, Frame and Stack Overflow
Thread Testing Program and Result
CPU Impact of Multi-Thread Applications
►I/O Impact of Multi-Thread Applications
FileEditor.java - I/O Intensive Process
►FileEditor2.java - Avoiding FileNotFoundException
MultithreadingIoRunner.java - Multiple I/O Threads
Running Multiple I/O Threads on JRockit
Micro Benchmark Runner and JVM Options
Micro Benchmark Tests on "int" Operations
Micro Benchmark Tests on "long" Operations
Micro Benchmark Tests in JIT Compilation Mode