Weak references to hidden classes - should be the default?

Mandy Chung 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 
ClassOption.STRONG option."

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 mailing list