Weak references to hidden classes - should be the default?
mandy.chung at oracle.com
Tue Mar 10 23:55:43 UTC 2020
Brian, John, et al,
Alex has given his feedback on the weak class feature (attached).
Alex recommends to change the default of hidden classes be weak classes
and introduce a ClassOption::STRONG option if it wants to ensure that
the hidden class is not being reclaimed until the class loader becomes
unreachable. See more details below.
We tried to keep a hidden class be a normal class from JVM's point of
view. Classes in the VM implementation have the same lifecycle as the
defining class loader. In addition, LambdaForms and Nashorn are the
only JDK use of hidden weak classes. All others such as lambda
metafactory and string concat use hidden (strong) classes as they are
part of the target class' internal implementation and should be unloaded
altogether. Hence strong reference to hidden classes is the default.
What's your recommendation?
-------- Forwarded Message --------
Subject: Weak references to hidden classes
Date: Tue, 10 Mar 2020 16:16:50 -0700
From: Alex Buckley <alex.buckley at oracle.com>
Organization: Oracle Corporation
To: Mandy Chung <mandy.chung at oracle.com>
JEP 371 says that a hidden class may be weakly referenced by its class
loader. Which loader? The only loader with any connection to a hidden
class is the loader nominated to serve as the defining loader by the API
spec of defineHiddenClass. However, that spec doesn't say "The defining
loader holds a strong reference to the hidden class" because no spec
says anything about how a class loader refers to a class.
(The only relationship we do specify is the other way around --
ClassLoader says "Every Class object contains a reference to the
ClassLoader that defined it." -- and happily that relationship holds for
a hidden class too.)
Point is, it's odd for defineHiddenClass to standardize how a class
loader refers to a hidden class when, conceptually, class loaders are
not meant to "know" about hidden classes.
(The connection between a defining loader and a hidden class is a mere
accounting trick done to support the hidden class's own code. No class
loader, not even that defining loader, knows how to respond to a class
load request for the hidden class.)
It's especially odd for defineHiddenClass's default to be a strong
reference. That default aligns with ClassLoader::defineClass, the API
we're trying to avoid, and doesn't align with
Unsafe::defineAnonymousClass, the API we're trying to recreate!
I understand there are performance reasons to want a loader to use a
strong reference rather than a weak reference. Accepting that claim, I
recommend having the implementation use a weak reference by default,
having the spec allow that, then introducing ClassOption.STRONG to force
a strong reference. That is, specify that:
"In the absence of an option, the defining loader's relationship with
the hidden class is unspecified, and the loader implementation may use a
strong reference or a weak reference to keep track of the hidden class.
If a hidden class is not strongly referenced by the class loader which
is deemed to be its defining loader, then the hidden class can be
unloaded when library code no longer refers to it. Library developers
who wish to prevent the hidden class from being unloaded must ensure
that its Class object is never reclaimed, or else use the
I understand there is a concern that developers would not realize / be
surprised by getting a weak reference as the default implementation.
However, the planet-wide audience for defineHiddenClass is perhaps 500
developers. They already have to know what they're doing because the
features of hidden classes are already more limited than the features of
VM-anonymous classes., e.g., no constant pool patching. The usual "Java
should save developers from making silly mistakes" rule doesn't apply here.
More information about the valhalla-dev