Index: modules/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java =================================================================== --- modules/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java (revision 507861) +++ modules/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java (working copy) @@ -92,6 +92,10 @@ public void truncate(long fileDescriptor, long size) throws IOException; + /** + * Returns the page size for virtual memory allocation + * (allocation granularity). + */ public int getPageSize() throws IOException; public long open(byte[] fileName, int mode) throws FileNotFoundException; Index: modules/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java =================================================================== --- modules/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java (revision 507861) +++ modules/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java (working copy) @@ -56,6 +56,12 @@ private native int lockImpl(long fileDescriptor, long start, long length, int type, boolean wait); + /** + * Returns the page size for virtual memory allocation + * (allocation granularity). + * Note that this value for Windows differs from the one for the real + * page size (64K and 4K respectively). + */ public native int getPageSize(); public boolean lock(long fileDescriptor, long start, long length, int type, Index: modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c =================================================================== --- modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c (revision 507861) +++ modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c (working copy) @@ -114,6 +114,12 @@ return (jint) - 1; } +/** + * Returns the granularity of the starting address for virtual memory allocation. + * Class: org_apache_harmony_luni_platform_OSFileSystem + * Method: getPageSize + * Signature: ()I + */ JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSFileSystem_getPageSize (JNIEnv * env, jobject thiz) { @@ -121,7 +127,7 @@ if(!pageSize){ SYSTEM_INFO info; GetSystemInfo(&info); - pageSize = info.dwPageSize; + pageSize = info.dwAllocationGranularity; } return pageSize; } Index: modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java =================================================================== --- modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java (revision 507861) +++ modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java (working copy) @@ -43,6 +43,7 @@ import java.nio.channels.WritableByteChannel; import java.nio.channels.FileChannel.MapMode; import java.util.Arrays; +import org.apache.harmony.luni.platform.Platform; import junit.framework.TestCase; @@ -307,6 +308,27 @@ } /** + * Initializes large test file. + * + * @param file the file to be written + * @param size the content size to be written + * @throws FileNotFoundException + * @throws IOException + */ + private void writeLargeDataToFile(File file, int size) throws FileNotFoundException, + IOException { + FileOutputStream fos = new FileOutputStream(file); + byte[] buf = new byte[size]; + + try { + // we don't care about content - just need a particular file size + fos.write(buf); + } finally { + fos.close(); + } + } + + /** * @tests java.nio.channels.FileChannel#position() */ public void test_position_WriteOnly() throws Exception { @@ -1932,6 +1954,51 @@ } /** + * Tests map() method for the value of positions exceeding memory + * page size and allocation granularity size. + * + * @tests java.nio.channels.FileChannel#map(MapMode,long,long) + */ + public void test_map_LargePosition() throws IOException { + // Regression test for HARMONY-3085 + int[] sizes = { + 4096, // 4K size (normal page size for Linux & Windows) + 65536, // 64K size (alocation granularity size for Windows) + Platform.getFileSystem().getPageSize() // native page size + }; + final int CONTENT_LEN = 10; + + for (int i = 0; i < sizes.length; ++i) { + // reset the file and the channel for the iterations + // (for the first iteration it was done by setUp() + if (i > 0 ) { + fileOfReadOnlyFileChannel = File.createTempFile( + "File_of_readOnlyFileChannel", "tmp"); + fileOfReadOnlyFileChannel.deleteOnExit(); + readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel) + .getChannel(); + } + + writeLargeDataToFile(fileOfReadOnlyFileChannel, sizes[i] + 2 * CONTENT_LEN); + MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY, + sizes[i], CONTENT_LEN); + assertEquals("Incorrectly mapped file channel for " + sizes[i] + + " position (capacity)", CONTENT_LEN, mapped.capacity()); + assertEquals("Incorrectly mapped file channel for " + sizes[i] + + " position (limit)", CONTENT_LEN, mapped.limit()); + assertEquals("Incorrectly mapped file channel for " + sizes[i] + + " position (position)", 0, mapped.position()); + + // map not change channel's position + assertEquals(0, readOnlyFileChannel.position()); + + // Close the file and the channel before the next iteration + readOnlyFileChannel.close(); + fileOfReadOnlyFileChannel.delete(); + } + } + + /** * @tests java.nio.channels.FileChannel#write(ByteBuffer) */ public void test_writeLByteBuffer_Null() throws Exception {