Skip to content

Commit f97a412

Browse files
committed
5041655: Remove implNote; add special cases for negative and zero sizes; handle overflow; handle zero size on Windows; add test
1 parent 3916723 commit f97a412

File tree

4 files changed

+159
-18
lines changed

4 files changed

+159
-18
lines changed

src/java.base/share/classes/java/nio/channels/FileChannel.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,8 @@ public abstract MappedByteBuffer map(MapMode mode, long position, long size)
999999
*
10001000
* @param size
10011001
* The size of the locked region; must be non-negative, and the sum
1002-
* {@code position} + {@code size} must be non-negative
1002+
* {@code position} + {@code size} must be non-negative.
1003+
* A value of zero indicates the remainder of the file.
10031004
*
10041005
* @param shared
10051006
* {@code true} to request a shared lock, in which case this
@@ -1126,7 +1127,8 @@ public final FileLock lock() throws IOException {
11261127
*
11271128
* @param size
11281129
* The size of the locked region; must be non-negative, and the sum
1129-
* {@code position} + {@code size} must be non-negative
1130+
* {@code position} + {@code size} must be non-negative.
1131+
* A value of zero indicates the remainder of the file.
11301132
*
11311133
* @param shared
11321134
* {@code true} to request a shared lock,

src/java.base/share/classes/java/nio/channels/FileLock.java

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ public abstract class FileLock implements AutoCloseable {
127127
/**
128128
* Initializes a new instance of this class.
129129
*
130+
* <p> If {@code size} is zero, the entire file from {@code position}
131+
* onward is locked.
132+
*
130133
* @param channel
131134
* The file channel upon whose file this lock is held
132135
*
@@ -164,6 +167,9 @@ protected FileLock(FileChannel channel,
164167
/**
165168
* Initializes a new instance of this class.
166169
*
170+
* <p> If {@code size} is zero, the entire file from {@code position}
171+
* onward is locked.
172+
*
167173
* @param channel
168174
* The channel upon whose file this lock is held
169175
*
@@ -264,25 +270,49 @@ public final boolean isShared() {
264270
/**
265271
* Tells whether or not this lock overlaps the given lock range.
266272
*
267-
* @implNote
268-
* This method assumes that the parameters are non-negative and that
269-
* their sum does not overflow a {@code long}, but does not enforce
270-
* these preconditions as do the constructors; hence it is the caller's
271-
* responsibility to ensure that these parameters are valid.
273+
* <p> If {@code size} is negative, {@code false} is returned regardless
274+
* of the value of {@code position}. If {@code size} is zero, it means the
275+
* lock range is unbounded.
272276
*
273277
* @param position
274278
* The starting position of the lock range
275279
* @param size
276280
* The size of the lock range
277281
*
278-
* @return {@code true} if, and only if, this lock and the given lock
279-
* range overlap by at least one byte
282+
* @return {@code false} if, and only if, {@code size} is negative or this
283+
* lock and the given lock range do <em>not</em> overlap by at
284+
* least one byte
280285
*/
281286
public final boolean overlaps(long position, long size) {
282-
if (position + size <= this.position)
283-
return false; // That is below this
284-
if (this.position + this.size <= position)
285-
return false; // This is below that
287+
System.out.printf("%d %d %d %d%n", this.position, this.size,
288+
position, size);
289+
if (size < 0)
290+
return false;
291+
292+
// if size == 0 then the specified lock range is unbounded and
293+
// cannot be below the range of this lock
294+
if (size > 0) {
295+
try {
296+
if (Math.addExact(position, size) <= this.position)
297+
return false; // That is below this
298+
} catch (ArithmeticException ignored) {
299+
// the sum of position and size overflows the range of long
300+
// hence their mathematical sum is greater than this.position
301+
}
302+
}
303+
304+
// if this.size == 0 then the range of this lock is unbounded and
305+
// cannot be below the specified lock range
306+
if (this.size > 0) {
307+
try {
308+
if (Math.addExact(this.position, this.size) <= position)
309+
return false; // This is below that
310+
} catch (ArithmeticException ignored) {
311+
// the sum of this.position and this.size overflows the range of
312+
// long hence their mathematical sum is greater than position
313+
}
314+
}
315+
286316
return true;
287317
}
288318

src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -389,8 +389,15 @@ Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
389389
HANDLE h = (HANDLE)(handleval(env, fdo));
390390
DWORD lowPos = (DWORD)pos;
391391
long highPos = (long)(pos >> 32);
392-
DWORD lowNumBytes = (DWORD)size;
393-
DWORD highNumBytes = (DWORD)(size >> 32);
392+
DWORD lowNumBytes;
393+
DWORD highNumBytes;
394+
if (size == 0) {
395+
lowNumBytes = MAXDWORD;
396+
highNumBytes = MAXDWORD;
397+
} else {
398+
lowNumBytes = (DWORD)size;
399+
highNumBytes = (DWORD)(size >> 32);
400+
}
394401
BOOL result;
395402
DWORD flags = 0;
396403
OVERLAPPED o;
@@ -434,8 +441,15 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
434441
HANDLE h = (HANDLE)(handleval(env, fdo));
435442
DWORD lowPos = (DWORD)pos;
436443
long highPos = (long)(pos >> 32);
437-
DWORD lowNumBytes = (DWORD)size;
438-
DWORD highNumBytes = (DWORD)(size >> 32);
444+
DWORD lowNumBytes;
445+
DWORD highNumBytes;
446+
if (size == 0) {
447+
lowNumBytes = MAXDWORD;
448+
highNumBytes = MAXDWORD;
449+
} else {
450+
lowNumBytes = (DWORD)size;
451+
highNumBytes = (DWORD)(size >> 32);
452+
}
439453
BOOL result = 0;
440454
OVERLAPPED o;
441455
o.hEvent = 0;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 5041655
27+
* @summary Verify FileLock.overlaps
28+
* @run testng Overlaps
29+
*/
30+
import java.io.IOException;
31+
import java.nio.ByteBuffer;
32+
import java.nio.channels.FileChannel;
33+
import java.nio.channels.FileLock;
34+
import java.nio.file.Files;
35+
import java.nio.file.Path;
36+
37+
import static java.lang.Boolean.*;
38+
import static java.nio.file.StandardOpenOption.*;
39+
40+
import static org.testng.Assert.assertEquals;
41+
import org.testng.annotations.AfterClass;
42+
import org.testng.annotations.BeforeClass;
43+
import org.testng.annotations.DataProvider;
44+
import org.testng.annotations.Test;
45+
46+
public class Overlaps {
47+
private static final long POS = 27;
48+
private static final long SIZE = 42;
49+
50+
private static FileChannel fc;
51+
52+
@BeforeClass
53+
public void before() throws IOException {
54+
Path path = Files.createTempFile(Path.of("."), "foo", ".bar");
55+
fc = FileChannel.open(path, CREATE, WRITE, DELETE_ON_CLOSE);
56+
fc.position(POS);
57+
fc.write(ByteBuffer.wrap(new byte[(int)SIZE]));
58+
}
59+
60+
@AfterClass
61+
public void after() throws IOException {
62+
fc.close();
63+
}
64+
65+
@DataProvider
66+
public Object[][] ranges() {
67+
return new Object[][] {
68+
{POS, SIZE, -1,-1, FALSE},
69+
{POS, SIZE, 0, -1, FALSE},
70+
{POS, SIZE, POS - 1, -1, FALSE},
71+
{POS, SIZE, POS + SIZE/2, -1, FALSE},
72+
{POS, SIZE, POS + SIZE, -1, FALSE},
73+
{POS, SIZE, -1, POS, FALSE},
74+
{POS, SIZE, -1, POS + SIZE/2, TRUE},
75+
{POS, SIZE, POS - 2, 1, FALSE},
76+
{POS, SIZE, POS + 1, 1, TRUE},
77+
{POS, SIZE, POS + SIZE/2, 0, TRUE},
78+
{POS, SIZE, Long.MAX_VALUE, 2, FALSE},
79+
{POS, SIZE, POS + SIZE / 2, Long.MAX_VALUE, TRUE},
80+
{POS, SIZE, 0, 0, TRUE},
81+
{Long.MAX_VALUE - SIZE/2, 0, 0, SIZE, FALSE},
82+
{Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE/4, SIZE, TRUE},
83+
{Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE, 0, TRUE},
84+
{Long.MAX_VALUE - SIZE, 0, Long.MAX_VALUE - SIZE/2, 0, TRUE}
85+
};
86+
}
87+
88+
@Test(dataProvider = "ranges")
89+
public void overlaps(long lockPos, long lockSize, long pos, long size,
90+
boolean overlaps) throws IOException {
91+
try (FileLock lock = fc.lock(lockPos, lockSize, false)) {
92+
assertEquals(lock.overlaps(pos, size), overlaps);
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)