<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 8, 2023 at 2:47 PM Frederic Parain <<a href="mailto:frederic.parain@oracle.com">frederic.parain@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Dan,<br>
<br>
I've looked at your exploration of the Preload attribute. The LoaderTest <br>
test loads class A but it doesn't link it. HotSpot looks at the PreLoad <br>
attribute at class link time, not class load time (yes, the name is <br>
misleading), this is why class B is not loaded.<br></blockquote><div><br></div><div>Thanks Fred. I knew I had to be doing something wrong as I couldn't find anything in the jdk that would have accounted for it.</div><div><br></div><div>Interestingly, I missed this in part due to a behaviour difference between OpenJ9 and Hotspot - by the time OpenJ9 returns a j.l.Class instance, the vtables have been built and method sendTargets have been set. It appears Hotspot initializes the vtable in a separate pass.</div><div><br></div><div>--Dan</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Replacing the call to loadClass() with a call to Class.forName() to <br>
force the linking of the class will trigger the processing of the <br>
PreLoad attribute.<br>
<br>
<br>
public static void main(String[] args) throws Throwable {<br>
ARGS = args;<br>
<br>
ClassLoader cl = new LoaderTest2();<br>
Class<?> c = Class.forName(args[0], true, cl);<br>
System.out.println(""+c+"::loader="+c.getClassLoader());<br>
<br>
}<br>
<br>
<br>
Fred<br>
<br>
<br>
On 6/8/23 12:01 PM, Dan Heidinga wrote:<br>
> Thanks Dan and Fred for the clarification on the current spec and <br>
> Hotspot behaviour and John for suggesting we remove the attribute.<br>
><br>
> I think the problem with the current status quo for the preload <br>
> attribute is that we're trying to treat it like an optimization - a <br>
> "we can have our cake" (know which classes to load at some <br>
> indeterminate point) and "eat it too" (not promise users anything <br>
> about when or if those classes will be loaded).<br>
><br>
> As it stands, based just on the spec, it's hard for users to know what <br>
> the preload attribute will do for them. There's nothing they can <br>
> depend on in the spec and are at the mercy of whatever behaviour VM <br>
> implementers pick on a given day. Which means they will depend on the <br>
> current Hotspot behaviour (defacto standardization - yuck!) or expect <br>
> the behaviour to change all the time.<br>
><br>
> If we decouple the list of preloadable classes from the classfile, how <br>
> would non-jdk classes be handled? Many applications are a mix of <br>
> multiple jar files from different maintenance domains which would make <br>
> having a combined list difficult. We'd also need to think through the <br>
> classloader implications vs today's approach which attempts to load on <br>
> the same loader as the class with the preload attribute.<br>
><br>
> What if instead of ditching the attribute, or treating it like an <br>
> optimization, we firmed up the contract and treated it as a guarantee <br>
> similar to those of superclasses and superinterfaces as in the first <br>
> line in section 5.4 "Linking"? The new text would read something like:<br>
> > Linking a class or interface involves verifying and preparing <br>
> that class or interface, its direct superclass, its direct <br>
> superinterfaces, and its element type (if it is an array type), if <br>
> necessary. Any classes listed in the preload attribute will be loaded <br>
> at this point.<br>
><br>
> We don't need to say in the JVMS why the classes are in the attribute, <br>
> but we should be explicit about where the attempt to load them occurs <br>
> and that errors are ignored. This provides stability to the users and <br>
> allows for independent implementation while avoiding de <br>
> facto standardization of today's behaviour.<br>
><br>
> Before responding, I built the latest lworld branch of the Valhalla <br>
> repo and played with the preload attribute to try and force a <br>
> classloader-related deadlock. I was surprised to find that the <br>
> attribute doesn't seem to have an effect on user-defined loaders and <br>
> with the current spec, I can't even say if that's a bug or not. <br>
> Example classfiles for this exploration are in <br>
> <a href="https://github.com/DanHeidinga/valhalla-preload-example" rel="noreferrer" target="_blank">https://github.com/DanHeidinga/valhalla-preload-example</a><br>
><br>
> --Dan<br>
><br>
> On Mon, Jun 5, 2023 at 9:52 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:<br>
><br>
> Overall, as we look at Preload, it is looking more and more like a<br>
> no-op, as far as the JLS and JVMS is concerned. Perhaps that is a<br>
> signal that it should be placed somewhere outside of the JVMS,<br>
> such as in a Leyden-specific mechanism (a preload list) produced<br>
> in a way decoupled from any transactions between the JLS and JVMS.<br>
><br>
> On 1 Jun 2023, at 11:24, Dan Smith wrote:<br>
><br>
> On Jun 1, 2023, at 10:53 AM, Dan Heidinga<br>
> <<a href="mailto:heidinga@redhat.com" target="_blank">heidinga@redhat.com</a>> wrote:<br>
><br>
> A couple of questions about the spec for the Preload<br>
> attribute[0]. The current spec says it indicates "certain<br>
> classes contain information that may be of interest during<br>
> linkage."<br>
><br>
> The Preload attribute removes one need for Q modifiers<br>
> while allowing calling convention optimizations and layout<br>
> decisions to be made early.<br>
><br>
> The current spec is quite vague on what classes should be<br>
> included in the attribute and on when / what the VM will<br>
> do with those classes (or even if it does anything).<br>
><br>
> FWIW, the JEP has more detail about when javac is expected to<br>
> include classes in Preload.<br>
><br>
> I think it's time to tighten up the spec for Preload<br>
> attribute and specify:<br>
> * what the VM will do with classes listed in the attribute<br>
><br>
> It is intentional that the VM may choose to do nothing. So<br>
> anything it does is purely an optimization.<br>
><br>
> Looks like a nop…<br>
><br>
> (In particular, it should not /reject/ any inputs, because that<br>
> would destabilize separate compilability in unpredictable ways.)<br>
><br>
> * when those classes will be loaded (ie: somewhere in JVMS<br>
> 5.3)<br>
><br>
> If the VM chooses to load Preload classes, then our thinking<br>
> was that JVMS 5.4 already describes the details of timing:<br>
><br>
> <a href="https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-5.html#jvms-5.4" rel="noreferrer" target="_blank">https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-5.html#jvms-5.4</a><br>
><br>
> So, for example, "Alternatively, an implementation may choose<br>
> an "eager" linkage strategy, where all symbolic references are<br>
> resolved at once when the class or interface is being<br>
> verified." That is, the Preload classes could all be loaded<br>
> during verification, or at some other stage of linking.<br>
><br>
> My expectation is that the natural point for processing<br>
> Preload is during preparation as vtables are set up, but<br>
> sometimes I get these things wrong. :-)<br>
><br>
> Sometimes you want them early (for instance layout) and sometimes<br>
> you need to wait (vtable layout or even just before <clinit>).<br>
><br>
> * how invalid cases are handled, including circularities<br>
> (Class A's Preload mentions B <: A)<br>
><br>
> Silent supression of errors, if any. Again, like a nop…<br>
><br>
> "Errors detected during linkage are thrown at a point in the<br>
> program where some action is taken by the program that might,<br>
> directly or indirectly, require linkage to the class or<br>
> interface involved in the error."<br>
><br>
> I've always found this rule super vague, but I think "require"<br>
> is the key word, and implies that errors caused by Preload<br>
> resolution should just be ignored. (Because Preload isn't<br>
> "required" to be processed at all.)<br>
><br>
> * what types of classes can be listed (any? only values?)<br>
><br>
> Definitely intend to support any classes of interest. Say a<br>
> future optimization wants to know about a sealed<br>
> superinterface, for example—it would be fine to tweak javac to<br>
> add that interface to Preload, and then use the information to<br>
> facilitate the optimization.<br>
><br>
> There's a lot of nondeterminism here—can a compliant system<br>
> trigger changes to class loading timing, but just on my<br>
> birthday?—but I think it's within the scope of JVMS 5.4, which<br>
> provides a lot of latitude for loading classes whenever it's<br>
> convenient.<br>
><br>
> It probably makes sense to start from the current Hotspot<br>
> handling of the attribute and fine tune that into the spec?<br>
><br>
> So I've outlined our hands-off stake in the ground above. The<br>
> spec would definitely benefit, at least, from a non-normative<br>
> cross-reference to 5.4 and short explanation. Beyond that, I<br>
> think we'd be open to specifying more if we can agree<br>
> something more is needed...<br>
><br>
> I think we could get the benefits in Fred’s prototype (as he<br>
> describes) with a list that is decoupled from any particular class<br>
> file, and Leyden could deliver this list.<br>
><br>
> As you see, I’m kind of sour on a Preload attribute these days.<br>
><br>
<br>
</blockquote></div></div>