8264827: Large mapped buffer/segment crash the VM when calling isLoaded

Reviewed-by: alanb, mcimadamore
This commit is contained in:
Chris Hegarty 2021-04-12 11:21:34 +00:00
parent e604320bbd
commit 3c9858ddfb
5 changed files with 36 additions and 13 deletions

View File

@ -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
@ -75,8 +75,8 @@ class Bits { // package-private
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();

View File

@ -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
@ -61,10 +61,10 @@ import java.io.UncheckedIOException;
// 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);
@ -106,7 +106,7 @@ import java.io.UncheckedIOException;
// 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;

View File

@ -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
@ -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;
@ -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

View File

@ -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?

View File

@ -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
@ -297,6 +297,29 @@ public class TestByteBuffer {
}
}
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);