In StringJoiner::toString final int addLen = prefix.length() + suffix.length();
Looks suspicious. There is no check for overflow here. Looking at the constructor it should have raised a OOM much earlier. Will investigate and file a bug. Thanks. -- Jim > On Jul 15, 2020, at 1:21 PM, Thomas Schatzl <thomas.scha...@oracle.com> wrote: > > Hi, > > I looked a bit at the allocations themselves, but first answering questions. > > On 15.07.20 15:25, David Holmes wrote: > > On 15/07/2020 10:18 pm, Jim Laskey wrote: > >> Thomas explained: That large objects are never moved (outstanding > >> issue) So, it's possible to fragment the -Xmx4g such that a 2G object > >> can't be allocated, > > > > Naively one would expect that whatever memory was consumed by > > > > String maxString = "*".repeat(MAX_ARRAY_LENGTH); > > > > in OOM2, would be fully freed and available for use by the same > > statememt in OOM3. But without knowing the exact allocation patterns > > This is true. > > Augmenting OOM3 code with allocations/gcs: > > Heap has 2.05g (1030 regions) > Allocation 1 for 1025 regions, 2g > > - concurrent mark start pause because of humongous allocation attempt; heap > has 2.05g > - not enough free space, so do a young collection, elevate to full > collection -> heap shrunk to 2M > - allocation goes through > > 1) String maxString = "*".repeat(MAX_ARRAY_LENGTH); > try { > > Allocation 2 for 2048 regions(!), 4g > - concurrent start pause because of humongous allocation attempt > - not enough free space, so do a young collection, elevate to full > collection -> heap stays at 2.05g -> OOME > > 2) new StringJoiner(maxString, "", maxString).toString(); > fail("Should have thrown OutOfMemoryError"); > > Two observations: > - I ask myselves how that test could have ever failed (i.e. not throw an > OOME). A 4g allocation on a 4g heap can in practice never succeed. This is > very suspicious. > > - It is also interesting why Allocation 2 internally has been truncated to a > 2048 region allocation. It should be 2049 (4g + 16 bytes header?). Checking > at lower layers, memory management get a request for 4294967296 bytes which > is exactly 2^32... this is too small for that object. Something is truncating > that string. Printing it gives a length of 2147483639 chars (i.e. 2^32-1-9). > I assume that is correct to silently truncate the result string? > > Thanks, > Thomas