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 513827) +++ modules/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java (working copy) @@ -92,7 +92,10 @@ public void truncate(long fileDescriptor, long size) throws IOException; - public int getPageSize() throws IOException; + /** + * Returns the granularity for virtual memory allocation. + */ + public int getAllocGranularity() 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 513827) +++ modules/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java (working copy) @@ -56,7 +56,12 @@ private native int lockImpl(long fileDescriptor, long start, long length, int type, boolean wait); - public native int getPageSize(); + /** + * Returns the granularity for virtual memory allocation. + * Note that this value for Windows differs from the one for the + * page size (64K and 4K respectively). + */ + public native int getAllocGranularity() throws IOException; public boolean lock(long fileDescriptor, long start, long length, int type, boolean waitFlag) throws IOException { Index: modules/luni/src/main/native/luni/unix/OSFileSystemLinux32.c =================================================================== --- modules/luni/src/main/native/luni/unix/OSFileSystemLinux32.c (revision 513827) +++ modules/luni/src/main/native/luni/unix/OSFileSystemLinux32.c (working copy) @@ -129,15 +129,21 @@ return (rc == -1) ? -1 : 0; } - -JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSFileSystem_getPageSize +/** + * Returns the granularity of the starting address for virtual memory allocation. + * (It's the same as the page size.) + * Class: org_apache_harmony_luni_platform_OSFileSystem + * Method: getAllocGranularity + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSFileSystem_getAllocGranularity (JNIEnv * env, jobject thiz) { - static int pageSize = 0; - if(pageSize == 0){ - pageSize = getpagesize(); + static int allocGranularity = 0; + if(allocGranularity == 0){ + allocGranularity = getpagesize(); } - return pageSize; + return allocGranularity; } /* Index: modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c =================================================================== --- modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c (revision 513827) +++ modules/luni/src/main/native/luni/windows/OSFileSystemWin32.c (working copy) @@ -114,16 +114,23 @@ return (jint) - 1; } -JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSFileSystem_getPageSize +/** + * Returns the granularity of the starting address for virtual memory allocation. + * (Note, that it differs from page size.) + * Class: org_apache_harmony_luni_platform_OSFileSystem + * Method: getAllocGranularity + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_apache_harmony_luni_platform_OSFileSystem_getAllocGranularity (JNIEnv * env, jobject thiz) { - static DWORD pageSize = 0; - if(!pageSize){ + static DWORD allocGranularity = 0; + if(!allocGranularity){ SYSTEM_INFO info; GetSystemInfo(&info); - pageSize = info.dwPageSize; + allocGranularity = info.dwAllocationGranularity; } - return pageSize; + return allocGranularity; } /* Index: modules/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java =================================================================== --- modules/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java (revision 513827) +++ modules/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java (working copy) @@ -48,11 +48,11 @@ // Reference to the portable file system code. private static final IFileSystem fileSystem = Platform.getFileSystem(); - private static final int NATIVE_PAGE_SIZE; + private static final int ALLOC_GRANULARITY; static { try { - NATIVE_PAGE_SIZE = fileSystem.getPageSize(); + ALLOC_GRANULARITY = fileSystem.getAllocGranularity(); } catch (IOException e) { throw new Error(e); } @@ -188,7 +188,7 @@ if (position + size > size()) { fileSystem.truncate(handle, position + size); } - long alignment = position - position % NATIVE_PAGE_SIZE; + long alignment = position - position % ALLOC_GRANULARITY; int offset = (int) (position - alignment); PlatformAddress address = PlatformAddressFactory.allocMap(handle, alignment, size + offset, mapMode); 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 513827) +++ 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().getAllocGranularity() // alloc granularity + }; + 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 {