In the same light the test in String::replace int resultLen; try { resultLen = Math.addExact(valLen, Math.multiplyExact(++p, replLen - targLen)); } catch (ArithmeticException ignored) { throw new OutOfMemoryError("String resulting from replace exceeds maximum string size"); }
Is useless in this situation (from the bug report): int missingToIntMax = 10; String tooLarge = "a".repeat(Integer.MAX_VALUE - missingToIntMax); tooLarge.replace("a", "a".repeat(missingToIntMax + 2)); The replace "test" does not fail and the exception comes from further down the stack: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.base/java.util.Arrays.copyOf(Arrays.java:3584) at java.base/java.lang.StringLatin1.replace(StringLatin1.java:349) at java.base/java.lang.String.replace(String.java:2173) at JI9062163.main(JI9062163.java:6) > On May 31, 2020, at 10:15 PM, Martin Buchholz <marti...@google.com> wrote: > > I'm still not deeply reading the code in java.nio but I see in > AbstractStringBuilder > > * Will not return a capacity greater than > * {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity > * is greater than that. > > My intent was that a garden variety grow method would first grow to > MAX_ARRAY_SIZE, then to Integer.MAX_VALUE. > > (this doesn't always work, e.g. hash tables want to have a > power-of-two sized backing array) > > (these methods have evolved recently without much help from me) > > (Library code should know as little about VM implementation > idiosyncrasies as possible) > > On Sun, May 31, 2020 at 5:56 PM David Holmes <david.hol...@oracle.com> wrote: >> >> On 1/06/2020 9:52 am, Martin Buchholz wrote: >>> On Sun, May 31, 2020 at 4:35 PM David Holmes <david.hol...@oracle.com> >>> wrote: >>> >>>> Not sure how we could have minCapacity < 0 at this point. It should have >>>> been checked before the call to grow, and grow will not make it negative. >>> >>> At least some of the grow methods were designed so that callers did >>> not have to do the checking, and grow would interpret negative values >>> as int overflow >>> >>>>> It just seems that it's pushing the inevitable off to Arrays.copyOf. >>>>> Shouldn't it be: >>>>> >>>>> private static int hugeCapacity(int minCapacity) { >>>>> if (minCapacity < 0 || minCapacity > MAX_ARRAY_SIZE) { >>>>> throw >>>>> new OutOfMemoryError("ByteArrayChannel exceeds maximum >>>>> size: " + >>>>> MAX_ARRAY_SIZE); >>>>> } >>>>> >>>>> return MAX_ARRAY_SIZE; >>>>> } >>>> >>>> That seems more appropriate to me - modulo the question mark over >>>> minCapacity being negative. >>> >>> Again, the original design was to allow a capacity with MAX_ARRAY_SIZE >>> < capacity <= Integer.MAX_VALUE if and when the VM also allowed it. >> >> The only way to know that is to try and create the array, catch the OOME >> and then adjust the value used. None of the code does that so I can't >> see how your claim here can be correct. My understanding, having been on >> the VM side, was that Hotspot's internal limits were reflected on the >> Java side so that the Java code could avoid the VM exception. >> >> David