JDK-6416884 : (fc) FileChannel.map throws IOExceptions with non-intuitive messages in some error situations
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-04-24
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b07Fixed
Related Reports
Relates :  
Relates :  
Description
Crated a File of size 100 bytes less Integer.MAX_VALUE.

1)When tried to map this file region from postion 0. it throws "IOException:The parameter is incorrect" on windows but it doesnt throw any exception on solaris

Parameters passed to FileChannel.map method are as per spec
 mode - MapMode.READ_ONLY
 position - 0
 size = 2147483549 ( less than Integer.MAX_VALUE )
 
2)if the following Parameters passed to FileChannel.map then the Exception message is "Access is denied" on windows ,"bad file number" on solaris , if region to be mapped is 
decreased to 10000, it doesnt throw any exception as in case 3.
 
 mode - MapMode.READ_ONLY
 position - 1
 size = 2147483549 ( less than Integer.MAX_VALUE )

3) doesnt throw any Exception for the following parameters
 mode - MapMode.READ_ONLY
 position - 0/1
 size = 10000 

Please See the following Code and Result
<version>        
java version "1.6.0-beta2"
Java(TM) SE Runtime Environment (build 1.6.0-beta2-b80)
Java HotSpot(TM) Client VM (build 1.6.0-beta2-b80, mixed mode)
</version>
1)        
<Code>
import java.io.*;
import java.nio.channels.*;
import java.nio.*;

public class TestFile {
   public static void main(String... args) {

        try {
            File fn = new File("gbfile");
            //Creating a file 100 byts less 2GB file.
            RandomAccessFile raf = new RandomAccessFile(fn,"rw");
            long size = (1024L * 1024L * 1024L) * 2L;
            raf.seek ( size - 101 );
            raf.write( 1 );
            raf.close();

            //Mapping the created File
            FileInputStream fis =   new FileInputStream(fn);
            FileChannel fc = fis.getChannel();
            System.out.println("File size : "+ fc.size() +" << "+ " Integer.MAX_VALUE = "+Integer.MAX_VALUE + ((fc.size() < Integer.MAX_VALUE)?" yes":" no"));
            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0,fc.size());
	 }catch( IOException e) {
		e.printStackTrace ();
	 }
      }

}

</Code>
<Result on windows>
File size : 2147483549 <<  Integer.MAX_VALUE = 2147483647 yes
java.io.IOException: The parameter is incorrect
        at sun.nio.ch.FileChannelImpl.map0(Native Method)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:742)
        at TestFile.main(TestFile.java:21)
</Result on windows>
<Result on Solaris>
# /net/sqindia.india/export/disk09/jdk/1.6.0/latest/binaries/solsparc/bin/java TestFile
File size : 2147483548 <<  Integer.MAX_VALUE = 2147483647 yes
<Result on Solaris>

2)
<Code>
//Same as Above Program except the position within the file at which the mapped region is to start 1
import java.io.*;
import java.nio.channels.*;
import java.nio.*;

public class TestFile {
    public static void main(String... args) {

        try {
            File fn = new File("gbfile");
            //Creating a file 100 byts less 2GB file.
            RandomAccessFile raf = new RandomAccessFile(fn,"rw");
            long size = (1024L * 1024L * 1024L) * 2L;
            raf.seek ( size - 101 );
            raf.write( 1 );
            raf.close();

            //Mapping the created File
            FileInputStream fis =   new FileInputStream(fn);
            System.out.println("Can Read " + fn.canRead());
            FileChannel fc = fis.getChannel();
            System.out.println("File size : "+ fc.size() +" << "+ " Integer.MAX_VALUE = "+Integer.MAX_VALUE + ((fc.size() < Integer.MAX_VALUE)?" yes":" no"));
            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 1,fc.size());
	}catch( IOException e) {
		e.printStackTrace ();
	}
    }
}

</Code>
<Result on windows>
Can Read true
File size : 2147483549 <<  Integer.MAX_VALUE = 2147483647 yes
java.io.IOException: Access is denied
        at sun.nio.ch.FileChannelImpl.truncate0(Native Method)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:731)
        at TestFile.main(TestFile.java:22)
</Result on windows>
<Result on Solaris>
Can Read true
File size : 2147483548 <<  Integer.MAX_VALUE = 2147483647 yes
java.io.IOException: Bad file number
        at sun.nio.ch.FileChannelImpl.truncate0(Native Method)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:731)
        at TestFile.main(TestFile.java:43)
</Result on Solaris>

3)
<Code>
import java.io.*;
import java.nio.channels.*;
import java.nio.*;

public class TestFile {
    public static void main(String... args) {

        try {
            File fn = new File("gbfile");
            //Creating a file 100 byts less 2GB file.
            RandomAccessFile raf = new RandomAccessFile(fn,"rw");
            long size = (1024L * 1024L * 1024L) * 2L;
            raf.seek ( size - 101 );
            raf.write( 1 );
            raf.close();

            //Mapping the created File
            FileInputStream fis =   new FileInputStream(fn);
            System.out.println("Can Read " + fn.canRead());
            FileChannel fc = fis.getChannel();
            System.out.println("File size : "+ fc.size() +" << "+ " Integer.MAX_VALUE = "+Integer.MAX_VALUE + ((fc.size() < Integer.MAX_VALUE)?" yes":" no"));
            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 1,10000);
	}catch( IOException e) {
		e.printStackTrace ();
	}
    }
}
</Code>
<Result on windows>
C:\home\rg157576\tmpjava>java TestFile
Can Read true
File size : 2147483548 <<  Integer.MAX_VALUE = 2147483647 yes
<Result on windows>
<Result on Solaris>
# /net/sqindia.india/export/disk09/jdk/1.6.0/latest/binaries/solsparc/bin/java TestFile
Can Read true
File size : 2147483548 <<  Integer.MAX_VALUE = 2147483647 yes
</Result on Solaris >

Comments
EVALUATION -- Further to the above, we will address this bug in jdk7 by throwing an IOException with an intuitive message rather than attempting to extend the file and throwing an IOException with a mis-leading message (for the read-write case we will attempt to extend the file as we do now).
08-12-2006

EVALUATION The are essentially two issues here: 1. A process is limited to 2GB of virtual memory on 32-bit editions of Windows which means it is not possible to map a region close to that size. If sharing is disabled (-Xshare:off or use server VM) then it should be possible to map a region up to ~1.6GB. It will be less than this if the java heap needs to be increased beyond its default. If sharing is enabled then the maximum will be reduced to about ~1-1.1GB. 2. The behaviour of the map method is not specified when the requested region is not completely contained within the file. In our implementation we attempt to extend the file but that fails if the file is opened for reading only (this explains the "access denied" and "bad file number" errors).
24-04-2006