diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 2c14fa9687e..636230d8f38 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -857,20 +857,18 @@ public class FileChannelImpl if (position > sz) return 0; - // Now position <= sz so remaining >= 0 and - // remaining == 0 if and only if sz == 0 - long remaining = sz - position; - - // Adjust count only if remaining > 0, i.e., - // sz > position which means sz > 0 - if (remaining > 0 && remaining < count) - count = remaining; - // System calls supporting fast transfers might not work on files // which advertise zero size such as those in Linux /proc if (sz > 0) { - // Attempt a direct transfer, if the kernel supports it, limiting - // the number of bytes according to which platform + // Now sz > 0 and position <= sz so remaining >= 0 and + // remaining == 0 if and only if sz == position + long remaining = sz - position; + + if (remaining >= 0 && remaining < count) + count = remaining; + + // Attempt a direct transfer, if the kernel supports it, + // limiting the number of bytes according to which platform int icount = (int) Math.min(count, nd.maxDirectTransferSize()); long n; if ((n = transferToDirect(position, icount, target)) >= 0) diff --git a/test/jdk/java/nio/channels/FileChannel/Transfer.java b/test/jdk/java/nio/channels/FileChannel/Transfer.java index 453230fff95..51adba60b06 100644 --- a/test/jdk/java/nio/channels/FileChannel/Transfer.java +++ b/test/jdk/java/nio/channels/FileChannel/Transfer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 + * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 8325382 * @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed) * @library .. * @library /test/lib @@ -48,11 +48,13 @@ import java.nio.channels.Pipe; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; +import java.nio.file.Files; import java.util.Random; import java.util.concurrent.TimeUnit; import jdk.test.lib.RandomFactory; +import org.testng.Assert; import org.testng.annotations.Test; public class Transfer { @@ -158,6 +160,33 @@ public class Transfer { } } + @Test + public void transferToNoThrow() throws IOException { // for bug 8325382 + File source = File.createTempFile("before", "after"); + source.deleteOnExit(); + + CharSequence csq = "Reality is greater than the sum of its parts."; + Files.writeString(source.toPath(), csq); + final long length = csq.length(); + Assert.assertEquals(source.length(), length); + + File target = File.createTempFile("before", "after"); + target.deleteOnExit(); + + try (FileInputStream in = new FileInputStream(source); + FileOutputStream out = new FileOutputStream(target); + FileChannel chSource = in.getChannel(); + FileChannel chTarget = out.getChannel()) { + // The count of bytes requested to transfer must exceed + // FileChannelImpl.MAPPED_TRANSFER_THRESHOLD which is + // currently 16384 + long n = chSource.transferTo(length, 16385, chTarget); + + // At the end of the input so no bytes should be transferred + Assert.assertEquals(n, 0); + } + } + @Test public void xferTest02() throws Exception { // for bug 4482726 byte[] srcData = new byte[5000];