8341243: Use ArraySupport.SOFT_MAX_ARRAY_LENGTH for max array size in java.base

Reviewed-by: jpai, smarks
This commit is contained in:
Eirik Bjørsnøs 2024-10-02 01:27:03 +00:00 committed by Jaikiran Pai
parent 8d6d37fea1
commit 0f381137cb
15 changed files with 51 additions and 41 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,8 @@
package java.io; package java.io;
import jdk.internal.util.ArraysSupport;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -305,12 +307,9 @@ public abstract class InputStream implements Closeable {
} }
/** /**
* The maximum size of array to allocate. * The maximum size of array to allocate
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/ */
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; private static final int MAX_BUFFER_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/** /**
* Reads all remaining bytes from the input stream. This method blocks until * Reads all remaining bytes from the input stream. This method blocks until

View File

@ -38,6 +38,7 @@ import java.io.Serializable;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ArraysSupport;
/** /**
* Resizable-array implementation of the {@link Deque} interface. Array * Resizable-array implementation of the {@link Deque} interface. Array
@ -124,12 +125,9 @@ public class ArrayDeque<E> extends AbstractCollection<E>
transient int tail; transient int tail;
/** /**
* The maximum size of array to allocate. * The maximum size of array to allocate
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/ */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static final int MAX_ARRAY_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/** /**
* Increases the capacity of this deque by at least the given amount. * Increases the capacity of this deque by at least the given amount.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1184,7 +1184,7 @@ public class BitSet implements Cloneable, java.io.Serializable {
public String toString() { public String toString() {
checkInvariants(); checkInvariants();
final int MAX_INITIAL_CAPACITY = Integer.MAX_VALUE - 8; final int MAX_INITIAL_CAPACITY = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
int numBits = (wordsInUse > 128) ? int numBits = (wordsInUse > 128) ?
cardinality() : wordsInUse * BITS_PER_WORD; cardinality() : wordsInUse * BITS_PER_WORD;
// Avoid overflow in the case of a humongous numBits // Avoid overflow in the case of a humongous numBits

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ArraysSupport;
/** /**
* This class implements a hash table, which maps keys to values. Any * This class implements a hash table, which maps keys to values. Any
@ -390,12 +391,9 @@ public class Hashtable<K,V>
} }
/** /**
* The maximum size of array to allocate. * The maximum size of array to allocate
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/ */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static final int MAX_ARRAY_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/** /**
* Increases the capacity of and internally reorganizes this * Increases the capacity of and internally reorganizes this

View File

@ -69,6 +69,7 @@ import java.util.function.ToLongBiFunction;
import java.util.function.ToLongFunction; import java.util.function.ToLongFunction;
import java.util.stream.Stream; import java.util.stream.Stream;
import jdk.internal.misc.Unsafe; import jdk.internal.misc.Unsafe;
import jdk.internal.util.ArraysSupport;
/** /**
* A hash table supporting full concurrency of retrievals and * A hash table supporting full concurrency of retrievals and
@ -517,7 +518,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* The largest possible (non-power of two) array size. * The largest possible (non-power of two) array size.
* Needed by toArray and related methods. * Needed by toArray and related methods.
*/ */
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; static final int MAX_ARRAY_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/** /**
* The default concurrency level for this table. Unused but * The default concurrency level for this table. Unused but

View File

@ -1502,8 +1502,8 @@ public final class Pattern
return "\\Q" + s + "\\E"; return "\\Q" + s + "\\E";
int lenHint = s.length(); int lenHint = s.length();
lenHint = (lenHint < Integer.MAX_VALUE - 8 - lenHint) ? lenHint = (lenHint < ArraysSupport.SOFT_MAX_ARRAY_LENGTH - lenHint) ?
(lenHint << 1) : (Integer.MAX_VALUE - 8); (lenHint << 1) : ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
StringBuilder sb = new StringBuilder(lenHint); StringBuilder sb = new StringBuilder(lenHint);
sb.append("\\Q"); sb.append("\\Q");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
*/ */
package java.util.stream; package java.util.stream;
import jdk.internal.util.ArraysSupport;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -57,7 +59,7 @@ final class Nodes {
/** /**
* The maximum size of an array that can be allocated. * The maximum size of an array that can be allocated.
*/ */
static final long MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; static final long MAX_ARRAY_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
// IllegalArgumentException messages // IllegalArgumentException messages
static final String BAD_SIZE = "Stream size exceeds max array size"; static final String BAD_SIZE = "Stream size exceeds max array size";

View File

@ -379,7 +379,7 @@ public abstract sealed class AbstractMemorySegmentImpl
throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length)); throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length));
} }
long arraySize = length / elemSize; long arraySize = length / elemSize;
if (arraySize > (Integer.MAX_VALUE - 8)) { //conservative check if (arraySize > ArraysSupport.SOFT_MAX_ARRAY_LENGTH) { //conservative check
throw new IllegalStateException(String.format("Segment is too large to wrap as %s. Size: %d", typeName, length)); throw new IllegalStateException(String.format("Segment is too large to wrap as %s. Size: %d", typeName, length));
} }
return (int)arraySize; return (int)arraySize;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,6 +36,7 @@ import java.util.*;
import java.util.jar.Attributes; import java.util.jar.Attributes;
import java.util.jar.Manifest; import java.util.jar.Manifest;
import jdk.internal.util.ArraysSupport;
import sun.security.action.GetIntegerAction; import sun.security.action.GetIntegerAction;
import sun.security.jca.Providers; import sun.security.jca.Providers;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
@ -87,8 +88,8 @@ public class SignatureFileVerifier {
// the maximum allowed size in bytes for the signature-related files // the maximum allowed size in bytes for the signature-related files
public static final int MAX_SIG_FILE_SIZE = initializeMaxSigFileSize(); public static final int MAX_SIG_FILE_SIZE = initializeMaxSigFileSize();
// The maximum size of array to allocate. Some VMs reserve some header words in an array. // The maximum size of array to allocate
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static final int MAX_ARRAY_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
/** /**
* Create the named SignatureFileVerifier. * Create the named SignatureFileVerifier.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,11 +21,14 @@
* questions. * questions.
*/ */
import jdk.internal.util.ArraysSupport;
/** /**
* @test * @test
* @bug 8218227 * @bug 8218227
* @summary StringBuilder/StringBuffer constructor throws confusing * @summary StringBuilder/StringBuffer constructor throws confusing
* NegativeArraySizeException * NegativeArraySizeException
* @modules java.base/jdk.internal.util
* @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G) * @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G)
* @run main/othervm -Xms6G -Xmx6G HugeCapacity * @run main/othervm -Xms6G -Xmx6G HugeCapacity
*/ */
@ -43,7 +46,7 @@ public class HugeCapacity {
private static void testHugeInitialString() { private static void testHugeInitialString() {
try { try {
String str = "Z".repeat(Integer.MAX_VALUE - 8); String str = "Z".repeat(ArraysSupport.SOFT_MAX_ARRAY_LENGTH);
StringBuffer sb = new StringBuffer(str); StringBuffer sb = new StringBuffer(str);
} catch (OutOfMemoryError ignore) { } catch (OutOfMemoryError ignore) {
} catch (Throwable unexpected) { } catch (Throwable unexpected) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,11 +21,14 @@
* questions. * questions.
*/ */
import jdk.internal.util.ArraysSupport;
/** /**
* @test * @test
* @bug 8149330 8218227 * @bug 8149330 8218227
* @summary Capacity should not get close to Integer.MAX_VALUE unless * @summary Capacity should not get close to Integer.MAX_VALUE unless
* necessary * necessary
* @modules java.base/jdk.internal.util
* @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G) * @requires (sun.arch.data.model == "64" & os.maxMemory >= 8G)
* @run main/othervm -Xms6G -Xmx6G -XX:+CompactStrings HugeCapacity true * @run main/othervm -Xms6G -Xmx6G -XX:+CompactStrings HugeCapacity true
* @run main/othervm -Xms6G -Xmx6G -XX:-CompactStrings HugeCapacity false * @run main/othervm -Xms6G -Xmx6G -XX:-CompactStrings HugeCapacity false
@ -75,7 +78,7 @@ public class HugeCapacity {
private static void testHugeInitialString() { private static void testHugeInitialString() {
try { try {
String str = "Z".repeat(Integer.MAX_VALUE - 8); String str = "Z".repeat(ArraysSupport.SOFT_MAX_ARRAY_LENGTH);
StringBuilder sb = new StringBuilder(str); StringBuilder sb = new StringBuilder(str);
} catch (OutOfMemoryError ignore) { } catch (OutOfMemoryError ignore) {
} catch (Throwable unexpected) { } catch (Throwable unexpected) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
* @summary Make sure IAE is not thrown on `int` overflow, turning negative * @summary Make sure IAE is not thrown on `int` overflow, turning negative
* size. The test should either not throw any Throwable, or an OOME * size. The test should either not throw any Throwable, or an OOME
* with real Java heap space error (not "exceeds VM limit"). * with real Java heap space error (not "exceeds VM limit").
* @modules java.base/jdk.internal.util
* @requires sun.arch.data.model == "64" * @requires sun.arch.data.model == "64"
* @run junit/othervm XcodeOverflow * @run junit/othervm XcodeOverflow
*/ */
@ -37,6 +38,7 @@ import java.nio.charset.CharacterCodingException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.stream.Stream; import java.util.stream.Stream;
import jdk.internal.util.ArraysSupport;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@ -44,8 +46,8 @@ import org.junit.jupiter.params.provider.Arguments;
public class XcodeOverflow { public class XcodeOverflow {
private static Stream<Arguments> sizes() { private static Stream<Arguments> sizes() {
return Stream.of( return Stream.of(
// SOFT_MAX_ARRAY_LENGTH: copied from ArraysSupport. No overflow; no OOME. // No overflow; no OOME.
Arguments.of(Integer.MAX_VALUE - 8), Arguments.of(ArraysSupport.SOFT_MAX_ARRAY_LENGTH),
// overflow case: OOME w/ "Java heap space" is thrown on decoding // overflow case: OOME w/ "Java heap space" is thrown on decoding
Arguments.of(Integer.MAX_VALUE - 1000000) Arguments.of(Integer.MAX_VALUE - 1000000)

View File

@ -21,6 +21,7 @@
* questions. * questions.
*/ */
import jdk.internal.util.ArraysSupport;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -37,6 +38,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* Base64.Decoder.decode behavior with large, (Integer.MAX_VALUE) sized * Base64.Decoder.decode behavior with large, (Integer.MAX_VALUE) sized
* input array/buffer. Tests the private methods "encodedOutLength" and * input array/buffer. Tests the private methods "encodedOutLength" and
* "decodedOutLength". * "decodedOutLength".
* @modules java.base/jdk.internal.util
* @run junit/othervm --add-opens java.base/java.util=ALL-UNNAMED TestEncodingDecodingLength * @run junit/othervm --add-opens java.base/java.util=ALL-UNNAMED TestEncodingDecodingLength
*/ */
@ -45,7 +47,7 @@ import static org.junit.jupiter.api.Assertions.fail;
public class TestEncodingDecodingLength { public class TestEncodingDecodingLength {
// A value large enough to test the desired memory conditions in encode and decode // A value large enough to test the desired memory conditions in encode and decode
private static final int LARGE_MEM_SIZE = Integer.MAX_VALUE - 8; private static final int LARGE_MEM_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
private static final Base64.Decoder DECODER = Base64.getDecoder(); private static final Base64.Decoder DECODER = Base64.getDecoder();
private static final Base64.Encoder ENCODER = Base64.getEncoder(); private static final Base64.Encoder ENCODER = Base64.getEncoder();

View File

@ -36,6 +36,7 @@ import java.util.ArrayDeque;
import java.util.Collections; import java.util.Collections;
import java.util.Spliterator; import java.util.Spliterator;
import jdk.internal.util.ArraysSupport;
import junit.framework.Test; import junit.framework.Test;
public class ArrayDeque8Test extends JSR166TestCase { public class ArrayDeque8Test extends JSR166TestCase {
@ -86,7 +87,7 @@ public class ArrayDeque8Test extends JSR166TestCase {
return; return;
final Item e = fortytwo; final Item e = fortytwo;
final int maxArraySize = Integer.MAX_VALUE - 8; final int maxArraySize = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
assertThrows(OutOfMemoryError.class, assertThrows(OutOfMemoryError.class,
() -> new ArrayDeque<Item>(Integer.MAX_VALUE)); () -> new ArrayDeque<Item>(Integer.MAX_VALUE));

View File

@ -38,7 +38,7 @@
* @test id=default * @test id=default
* @summary Conformance testing variant of JSR-166 tck tests. * @summary Conformance testing variant of JSR-166 tck tests.
* @build * * @build *
* @modules java.management * @modules java.management java.base/jdk.internal.util
* @run junit/othervm/timeout=1000 JSR166TestCase * @run junit/othervm/timeout=1000 JSR166TestCase
*/ */
@ -47,7 +47,7 @@
* @summary Conformance testing variant of JSR-166 tck tests * @summary Conformance testing variant of JSR-166 tck tests
* with java security manager set to allow. * with java security manager set to allow.
* @build * * @build *
* @modules java.management * @modules java.management java.base/jdk.internal.util
* @run junit/othervm/timeout=1000 -Djava.security.manager=allow JSR166TestCase * @run junit/othervm/timeout=1000 -Djava.security.manager=allow JSR166TestCase
*/ */
@ -56,7 +56,7 @@
* @summary Test implementation details variant of JSR-166 * @summary Test implementation details variant of JSR-166
* tck tests with ForkJoinPool common parallelism. * tck tests with ForkJoinPool common parallelism.
* @build * * @build *
* @modules java.management * @modules java.management java.base/jdk.internal.util
* @run junit/othervm/timeout=1000 * @run junit/othervm/timeout=1000
* --add-opens java.base/java.util.concurrent=ALL-UNNAMED * --add-opens java.base/java.util.concurrent=ALL-UNNAMED
* --add-opens java.base/java.lang=ALL-UNNAMED * --add-opens java.base/java.lang=ALL-UNNAMED
@ -78,7 +78,7 @@
* JSR-166 tck tests apart from ForkJoinPool common * JSR-166 tck tests apart from ForkJoinPool common
* parallelism. * parallelism.
* @build * * @build *
* @modules java.management * @modules java.management java.base/jdk.internal.util
* @run junit/othervm/timeout=1000 * @run junit/othervm/timeout=1000
* --add-opens java.base/java.util.concurrent=ALL-UNNAMED * --add-opens java.base/java.util.concurrent=ALL-UNNAMED
* --add-opens java.base/java.lang=ALL-UNNAMED * --add-opens java.base/java.lang=ALL-UNNAMED