United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6253145 (fc) FileChannel.transferTo on Linux fails when going beyond 2GB boundary
JDK-6253145 : (fc) FileChannel.transferTo on Linux fails when going beyond 2GB boundary

Details
Type:
Bug
Submit Date:
2005-04-11
Status:
Closed
Updated Date:
2011-05-17
Project Name:
JDK
Resolved Date:
2011-05-17
Component:
core-libs
OS:
solaris_9,solaris_7,linux
Sub-Component:
java.nio
CPU:
x86,sparc
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.2,5.0
Fixed Versions:

Related Reports
Backport:
Duplicate:
Duplicate:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Linux SageTVMediaCenter 2.6.11 #4 Thu Mar 17 00:22:15 GMT 2005 i686 VIA Nehemiah CentaurHauls GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When using java.nio.channels.FileChannel.transferTo(long offset, long length, WritableByteChannel ch) with an offset greater than 2^32 the data that's actually transferred is not the correct data.  It ends up doing a modulus with 2^32 and only transferring data from within the first 2GB of the file.

This happens because in the JNI code for this on Linux it's using the sendfile() Linux API call. This call is not compliant with 64-bit offsets.

  From FileChannelImpl.c:

JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
					    jint srcFD,
					    jlong position, jlong count,
					    jint dstFD)
{
#ifdef __linux__
    off_t offset = (off_t)position;
    jlong n = sendfile(dstFD, srcFD, &offset, (size_t)count);
    if (n < 0) {
        jlong max = (jlong)java_lang_Integer_MAX_VALUE;
        if (count > max) {
            n = sendfile(dstFD, srcFD, &offset, (size_t)max);
            if (n >= 0) {
                return n;
            }
        }
        if ((errno == EINVAL) && ((ssize_t)count >= 0))
            return IOS_UNSUPPORTED_CASE;
	JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
    }
    return n;
#endif

...


REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
Don't use transferTo when transferring data that lies beyond the 2GB boundary.
###@###.### 2005-04-11 10:25:03 GMT

                                    

Comments
EVALUATION

The 2.6 kernel has a sendfile64 so we should use that where available. Where not available we need to handle the offset > 2GB case. This is something for early in jdk7 so that it gets well tested.
                                     
2006-12-02



Hardware and Software, Engineered to Work Together