Late cleanup of stack objects

Sam Pullara spullara at gmail.com
Mon Nov 7 07:29:59 UTC 2022


I am kind of annoyed this doesn't solve the problem (scoping the
allocation):

package org.example;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

public class Main1 {
    public static void main(String[] args) throws ExecutionException,
InterruptedException {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            var future = executor.submit(() -> {
                try {
                    System.out.println("Starting work");
                    {
                        var bigBuffer = new byte[1024 * 1024 * 1024];
                        System.out.println("bigBuffer size: " +
bigBuffer.length);
                    }
                    // bigBuffer = null;
                    slowIO();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
            future.get();
        }
    }

    private static void slowIO() throws InterruptedException {
        System.out.println("Starting slowIO");
        Thread.sleep(Long.MAX_VALUE);
    }
}


On Sun, Nov 6, 2022 at 11:16 PM Sam Pullara <spullara at gmail.com> wrote:

> I would be surprised if that memory is ever released, JITed or not unless
> hotspot starts to try and determine object lifetimes per line. I'd be
> curious and will run it myself what happens if you just put a block around
> the allocation and println.
>
> On Sat, Nov 5, 2022 at 10:28 AM Arnaud Masson <arnaud.masson at fr.ibm.com>
> wrote:
>
>>
>>
>> In the sync case, the big buffer is retained in heap during the slow IO
>> (until it eventually returns), even if it’s not needed anymore.
>>
>>
>>
>> Are you sure you see an issue there once this code is warmed up? If so,
>> are you running this in the IDE with the debugger (asking because the
>> debugger need to access locals will prevent the compiler from pruning
>> locals).
>>
>>
>> I just execute the main() entry once _*without*_ debugger (from IDE).
>>
>> I then check memory usage in VisualVM, and I force GC a few times to be
>> sure memory is really retained.
>>
>> The async app releases the big buffer but not the sync app. (The sync app
>> releases memory if I uncomment the null assignment.)
>>
>>
>>
>> By warmed-up, you mean it has been JIT-ed? It’s a bit outside the control
>> of a normal app, is it really supposed to have such an impact on object
>> strong ref lifetime?
>>
>>
>>
>> thanks
>>
>> Arnaud
>> Unless otherwise stated above:
>>
>> Compagnie IBM France
>> Siège Social : 17, avenue de l'Europe, 92275 Bois-Colombes Cedex
>> RCS Nanterre 552 118 465
>> Forme Sociale : S.A.S.
>> Capital Social : 664 069 390,60 €
>> SIRET : 552 118 465 03644 - Code NAF 6203Z
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20221106/fe2e6fee/attachment.htm>


More information about the loom-dev mailing list