Skip to content

Commit

Permalink
8264827: Large mapped buffer/segment crash the VM when calling isLoaded
Browse files Browse the repository at this point in the history
Reviewed-by: alanb, mcimadamore
  • Loading branch information
ChrisHegarty committed Apr 12, 2021
1 parent e604320 commit 3c9858d
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 13 deletions.
6 changes: 3 additions & 3 deletions src/java.base/share/classes/java/nio/Bits.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
Expand Down Expand Up @@ -75,8 +75,8 @@ static int pageSize() {
return PAGE_SIZE;
}

static int pageCount(long size) {
return (int)(size + (long)pageSize() - 1L) / pageSize();
static long pageCount(long size) {
return (size + (long)pageSize() - 1L) / pageSize();
}

private static boolean UNALIGNED = UNSAFE.unalignedAccess();
Expand Down
8 changes: 4 additions & 4 deletions src/java.base/share/classes/java/nio/MappedMemoryUtils.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
Expand Down Expand Up @@ -61,10 +61,10 @@ static void load(long address, boolean isSync, long size) {
// considering the loop as dead code.
Unsafe unsafe = Unsafe.getUnsafe();
int ps = Bits.pageSize();
int count = Bits.pageCount(length);
long count = Bits.pageCount(length);
long a = mappingAddress(address, offset);
byte x = 0;
for (int i=0; i<count; i++) {
for (long i=0; i<count; i++) {
// TODO consider changing to getByteOpaque thus avoiding
// dead code elimination and the need to calculate a checksum
x ^= unsafe.getByte(a);
Expand Down Expand Up @@ -106,7 +106,7 @@ static void force(FileDescriptor fd, long address, boolean isSync, long index, l

// native methods

private static native boolean isLoaded0(long address, long length, int pageCount);
private static native boolean isLoaded0(long address, long length, long pageCount);
private static native void load0(long address, long length);
private static native void unload0(long address, long length);
private static native void force0(FileDescriptor fd, long address, long length) throws IOException;
Expand Down
8 changes: 4 additions & 4 deletions src/java.base/unix/native/libnio/MappedMemoryUtils.c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, 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
Expand Down Expand Up @@ -56,11 +56,11 @@ static long calculate_number_of_pages_in_range(void* address, size_t len, size_t

JNIEXPORT jboolean JNICALL
Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong address,
jlong len, jint numPages)
jlong len, jlong numPages)
{
jboolean loaded = JNI_TRUE;
int result = 0;
int i = 0;
long i = 0;
void *a = (void *) jlong_to_ptr(address);
mincore_vec_t* vec = NULL;

Expand All @@ -70,7 +70,7 @@ Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong addres
if ((long)pagesize == -1) {
return JNI_FALSE;
}
numPages = (jint) calculate_number_of_pages_in_range(a, len, pagesize);
numPages = (jlong) calculate_number_of_pages_in_range(a, len, pagesize);
#endif

/* Include space for one sentinel byte at the end of the buffer
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/windows/native/libnio/MappedMemoryUtils.c
Expand Up @@ -32,7 +32,7 @@

JNIEXPORT jboolean JNICALL
Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong address,
jlong len, jint numPages)
jlong len, jlong numPages)
{
jboolean loaded = JNI_FALSE;
/* Information not available?
Expand Down
25 changes: 24 additions & 1 deletion test/jdk/java/foreign/TestByteBuffer.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, 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
Expand Down Expand Up @@ -297,6 +297,29 @@ public void testMappedSegmentOffset() throws Throwable {
}
}

static final long LARGE_SIZE = 3L * 1024L * 1024L * 1024L; // 3GB

@Test
public void testLargeMappedSegment() throws Throwable {
if (System.getProperty("sun.arch.data.model").equals("32")) {
throw new SkipException("large mapped files not supported on 32-bit systems");
}

File f = new File("testLargeMappedSegment.out");
f.createNewFile();
f.deleteOnExit();

try (MemorySegment segment = MemorySegment.mapFile(f.toPath(), 0, LARGE_SIZE, FileChannel.MapMode.READ_WRITE)) {
MappedMemorySegments.isLoaded(segment);
MappedMemorySegments.load(segment);
MappedMemorySegments.isLoaded(segment);
MappedMemorySegments.force(segment);
MappedMemorySegments.isLoaded(segment);
MappedMemorySegments.unload(segment);
MappedMemorySegments.isLoaded(segment);
}
}

static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long pos, long size, Consumer<MappedByteBuffer> action) throws Throwable {
MappedByteBuffer mbb = channel.map(mode, pos, size);
var ref = new WeakReference<>(mbb);
Expand Down

1 comment on commit 3c9858d

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.