Index: modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java =================================================================== --- modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java (revision 523024) +++ modules/nio/src/main/java/java/nio/MappedByteBufferAdapter.java (working copy) @@ -357,7 +357,6 @@ } public void free() { - ((MappedPlatformAddress)this.wrapped.getBaseAddress()).free(); this.wrapped.free(); } } 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 523024) +++ modules/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java (working copy) @@ -404,19 +404,27 @@ } ByteBuffer buffer = null; - if (src instanceof FileChannel) { - FileChannel fileSrc = (FileChannel) src; - long size = fileSrc.size(); - long filePosition = fileSrc.position(); - count = Math.min(count, size - filePosition); - buffer = fileSrc.map(MapMode.READ_ONLY, filePosition, count); - fileSrc.position(filePosition + count); - } else { - buffer = ByteBuffer.allocateDirect((int) count); - src.read(buffer); - buffer.flip(); + + try { + if (src instanceof FileChannel) { + FileChannel fileSrc = (FileChannel) src; + long size = fileSrc.size(); + long filePosition = fileSrc.position(); + count = Math.min(count, size - filePosition); + buffer = fileSrc.map(MapMode.READ_ONLY, filePosition, count); + fileSrc.position(filePosition + count); + } else { + buffer = ByteBuffer.allocateDirect((int) count); + src.read(buffer); + buffer.flip(); + } + return write(buffer, position); + } finally { + // unmap the buffer + if (buffer != null) { + ((DirectBuffer) buffer).free(); + } } - return write(buffer, position); } public long transferTo(long position, long count, WritableByteChannel target) @@ -443,8 +451,16 @@ return kernelTransfer(handle, ((SocketChannelImpl) target).getFD(), position, count); } - buffer = map(MapMode.READ_ONLY, position, count); - return target.write(buffer); + + try { + buffer = map(MapMode.READ_ONLY, position, count); + return target.write(buffer); + } finally { + // unmap the buffer + if (buffer != null) { + ((DirectBuffer) buffer).free(); + } + } } private long kernelTransfer(long l, FileDescriptor fd, long position, 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 523024) +++ modules/nio/src/test/java/common/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java (working copy) @@ -3162,6 +3162,52 @@ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get()); } } + + /** + * Regression test for Harmony-3324 + * Make sure we could delete the file after we called transferTo() method. + */ + public void test_transferTo_couldDelete() throws Exception { + // init data in files + writeDataToFile(fileOfReadOnlyFileChannel); + writeDataToFile(fileOfWriteOnlyFileChannel); + + // call transferTo() method + readOnlyFileChannel.transferTo(0 , 2, writeOnlyFileChannel); + + // delete both files + readOnlyFileChannel.close(); + writeOnlyFileChannel.close(); + boolean rDel = fileOfReadOnlyFileChannel.delete(); + boolean wDel = fileOfWriteOnlyFileChannel.delete(); + + // make sure both files were deleted + assertTrue("File " + readOnlyFileChannel + " exists", rDel); + assertTrue("File " + writeOnlyFileChannel + " exists", wDel); + } + + /** + * Regression test for Harmony-3324 + * Make sure we could delete the file after we called transferFrom() method. + */ + public void test_transferFrom_couldDelete() throws Exception { + // init data in files + writeDataToFile(fileOfReadOnlyFileChannel); + writeDataToFile(fileOfWriteOnlyFileChannel); + + // call transferTo() method + writeOnlyFileChannel.transferFrom(readOnlyFileChannel, 0 , 2); + + // delete both files + readOnlyFileChannel.close(); + writeOnlyFileChannel.close(); + boolean rDel = fileOfReadOnlyFileChannel.delete(); + boolean wDel = fileOfWriteOnlyFileChannel.delete(); + + // make sure both files were deleted + assertTrue("File " + readOnlyFileChannel + " exists", rDel); + assertTrue("File " + writeOnlyFileChannel + " exists", wDel); + } private class MockFileChannel extends FileChannel {