garbage collection and indy
John Rose
john.r.rose at oracle.com
Thu Aug 24 04:10:29 UTC 2023
I am not following every detail here, but as long as you have a variable
and/or an indy state that gives access to any part of a dynamically
loaded class, then that class will not be unloaded. There’s no way
to unload most of a class but keep one of its methods, for example.
And if the class is live, its class loader will be live as well.
So, indy or field -> MH or VH -> class -> loader is the chain
that keeps everything alive.
On 23 Aug 2023, at 1:09, Jochen Theodorou wrote:
> Am 22.08.23 um 22:38 schrieb Charles Oliver Nutter:
>> On Tue, Aug 22, 2023 at 3:07 PM Jochen Theodorou <blackdrag at gmx.org> wrote:
>>> Is there any possible circumstance in which the class Foo can now be
>>> garbage collected? My assumption is no.
>>
>> I can't speak to varhandles but this is very much like how JRuby
>> handles all of our jitted Ruby methods and indy binding. Under normal
>> circumstances, most Ruby methods get jit-compiled to bytecode lazily
>> and loaded into a unique classloader each; that classloader is not
>> rooted anywhere, so that if the Ruby method goes away, the jitted
>> class can also go away.
>
> But don't you get problems with the method going away and then being
> required again?
>
>> If the method was transient in the Ruby world (e.g. created on a
>> "singleton" object that goes out of scope) but is still bound at a
>> call site, it will not get garbage collected. We've actually had some
>> "won't fix" bug reports about indy call sites rooting methods or
>> classes that were called once (as is our expectation, not a bug).
>
> I can maybe actually make my description more clear with an example in
> pseudo Java:
>
> '''
> class ScriptRunner {
> public runScript10times(String script) {
> Object instance = compileJava(script)
> for (int i=0; i<10; i++) {
> instance.getClass().getMethod("run").invoke(instance)
> }
> }
> }
> '''
>
> where compileJava will compile the script into bytecode and load it
> under the assumption that it is a run() method. The script could be
> normal Java. Then compileJava would maybe leverage javac for this and a
> bit of reflection and a classloader that is only for that class to be
> defined in. Let us assume ScriptRunner will stay around for a long time
> and the classloader used is not referenced anywhere.
>
> Anyway... my assumption for Java would be now, that after the method
> call is done:
> * instance can be collected and is in fact pretty fast.
> * since instance and classloader are not referenced, the script class is
> becoming collectable
> * the script class can be collected once GC gets to it.
>
> Now let us assume ScriptRunner is almost Java, everything is the same,
> but the call to run()
> "instance.getClass().getMethod("run").invoke(instance)" is now done
> using invokedynamic "instance.run()". Let us assume there will be a
> runtime selection of the run method, that does something like the
> pseudo-Java version, unreflects the method and invokes the handle as
> well as installs it in the mutable callsite as target (with guards to
> detect a new script class).
>
> Then it seems to me like:
> * instance can be collected like above
> * the class will be hard/strong referenced by the MethodHandle instance
> type information in the callsite
> * the script class can be collected only once the callsite target is
> rewritten or the class ScriptRunner goes away.
>
> Am I wrong?
>
>
> bye Jochen
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.org
> https://mail.openjdk.org/mailman/listinfo/mlvm-dev
More information about the mlvm-dev
mailing list