Future of explicit class initialization APIs
Hello, I came across JDK-8246634, which proposed to add MethodHandles.Lookup.ensureInitialized to ensure a class is initialized before a Method Handle is invoked. However, this appears to be contrary to what project Leyden is aiming for. Explicit class initializations are mostly a hurdle to condensing computations to be available before JVM startup. Thus, I wonder if such an API addition is worth exploring. In the original RFE JDK-8235521, the main usages of ensureClassInitialized was barrier for static field accessors in MH (and now VH) and to ensure the side effects are performed by class initializers (as in SharedSecrets). Since it seems Project Leyden has done extensive research on class initialization patterns, I wonder if there are any other purposes for the ensureClassInitialized or Class.forName APIs (which performs explicit initialization), and how Leyden treats them for condensing. Such information would be helpful for deciding about the ensureInitialized for Method Handle API. Please don't hesitate to reply if you have other remarks about this RFE. Best, Chen Liang
The ensureInitialized call is something that could be called from Leyden-generated configuration activities that happen before main. Most such activities also involve some further optimization, like dumping a Class object into the archive, so in the end you can’t see ensureInitialized. But it is a logical link in the Leyden chain. It’s easier to talk about shifting (in the Leyden sense) the initialization of a class if there is an actual reflective method that can do the shifting of the initialization. Also, there are, very rarely, cases where circular initialization dependencies, among tightly coupled classes, need to be organized properly. (You can get errors and deadlocks if you fail.) One tactic for organizing such initializers is for some responsible party to “touch” the classes that need to be initialized together, in the right order, and in the same thread. You can often do this “touch” on a class by instantiating it or by reading one of its statics. But the only truly general way to do such a “touch” is to call ensureInitialized. After all, a particular class might not want you to instantiate it, or it might not offer you a static API point to access. I mentioned this comes up very rarely… Do you have a reason NOT to allow this method? Or are you just asking why we bothered to make it public after all this time? It’s part of the Leyden toolkit. — John
Thanks for the elaboration, John! The impression that ensureInitialized is dangerous as a user-accessible API is from the 2023 JVMLS talk about Class Loading, where side-effects and inconsistent Class-Loading occurrences hamper optimization efforts. There's definitely no reason to remove this API. Users can just fabricate a no-op static void "init" to load their own classes if they need, or to use Class.forName("name", true, loader). I was just wondering if the addition of a MH barrier version (so we can create a barrier MH that can elide the barrier in LambdaForm after first invocation, like the static accessor LambdaForms) is plausible within the context of Leyden. So, does such a init-barrier-for-a-MH API in 8246634 work fine with Leyden's condensation and delayed initialization, and is it still a worthy RFE after 3 years of Java's evolution? Chen Liang On Sun, Oct 22, 2023 at 3:31 AM John Rose <john.r.rose@oracle.com> wrote:
The ensureInitialized call is something that could be called from Leyden-generated configuration activities that happen before main. Most such activities also involve some further optimization, like dumping a Class object into the archive, so in the end you can’t see ensureInitialized. But it is a logical link in the Leyden chain. It’s easier to talk about shifting (in the Leyden sense) the initialization of a class if there is an actual reflective method that can do the shifting of the initialization.
Also, there are, very rarely, cases where circular initialization dependencies, among tightly coupled classes, need to be organized properly. (You can get errors and deadlocks if you fail.) One tactic for organizing such initializers is for some responsible party to “touch” the classes that need to be initialized together, in the right order, and in the same thread. You can often do this “touch” on a class by instantiating it or by reading one of its statics. But the only truly general way to do such a “touch” is to call ensureInitialized. After all, a particular class might not want you to instantiate it, or it might not offer you a static API point to access. I mentioned this comes up very rarely…
Do you have a reason NOT to allow this method? Or are you just asking why we bothered to make it public after all this time? It’s part of the Leyden toolkit.
— John
participants (2)
-
-
-
John Rose