<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Oct 27, 2022 at 8:28 PM Mark Reinhold <<a href="mailto:mark.reinhold@oracle.com" target="_blank">mark.reinhold@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">2022/10/21 19:49:36 -0700, Dan Heidinga <<a href="mailto:heidinga@redhat.com" target="_blank">heidinga@redhat.com</a>>:<br>
> Thanks for posting this document.  It provides a clear starting point for<br>
> us to move forward to start to address Leyden.<br>
<br>
Thanks, Dan, and thanks for your comments and questions.<br>
<br>
> A few questions based on my read through:<br>
> <br>
>> As long as a condenser preserves program meaning and does not impose<br>
>> constraints other than those accepted by the developer, an implementation has<br>
>> wide latitude to optimize the result.<br>
> <br>
> Does “an implementation” refer only to the JDK or are other parts of the<br>
> ecosystem - frameworks, libraries, etc - able to add their own condensers<br>
> as well?<br>
<br>
Good question!<br>
<br>
We’re concerned here primarily with any software system that’s claimed<br>
to be a conformant implementation of the Java Platform -- the JDK is<br>
merely the dominant and best-known example.  The components of such a<br>
system -- including any condensers -- can be held to the rigors of the<br>
Platform Specification and the JCK, thereby ensuring that they preserve<br>
the meanings of Java programs.<br>
<br>
Some people will, no doubt, want to write their own condensers, and<br>
obviously we’d like all condensers to preserve program meaning.  The<br>
current conformance regime (specification/RI/JCK), however, applies only<br>
to entire Platform implementations.  </blockquote><div><br></div><div>Interesting.  I'm hesitating to raise this as I don't want to derail the technical topics, but I recall that after jlink was released, it was necessary to update the definition of the "platform" to handle the subset runtimes created by jlink.  With the kinds of changes envisioned for condensers - including removing unused classes, fields & methods - will we need to update the definition of the platform again?  Updates of this nature tend to take a while on the legal front so I'm raising this early (and hoping it's already being thought about) so the project doesn't end up with conderners that can't be shipped due to conflicts with the platform definition.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">                                                         If we want to enable developers of<br>
external condensers to make certifiable claims of safety then we’ll need<br>
to extend the conformance regime to test standalone condensers.<br>
(Whether that needs to be a priority isn’t clear to me at the moment.)<br></blockquote><div><br></div><div>There will be gaps, especially early on given the incremental delivery plan, that frameworks will be eager to fill.  As long as we provide frameworks a way to implement custom condensers, then they'll be happy even if they can't make the conformance claims.  Many of them have adopted native image today which suffers from the same conformance risks.</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>
Enabling the foundational tooling of the JDK (jlink, or whatever) to run<br>
arbitrary condensers is attractive, but not without risk.  People could<br>
ship non-conformant condensers even if we extend the conformance regime,<br>
since there’d be no conformance requirement.  Developers could, perhaps<br>
unwittingly, use such condensers and wind up with broken programs.  So<br>
maybe we’ll support external condensers in the JDK toolchain but emit a<br>
warning when they’re used.<br>
<br></blockquote><div><br></div><div>I'm glad to hear there's a path forward here.  Warnings are a reasonable restriction for custom condensers. </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">
>> If a developer chooses condensers that shift sufficient computation from run<br>
>> time to earlier phases — which may require accepting many constraints — then<br>
>> a conforming Java implementation could even produce a fully-static<br>
>> platform-specific executable.<br>
> <br>
> Great to read this!  Especially in light of the recent announcement around<br>
> GraalCE moving under the OpenJDK umbrella, this provides wide latitude to<br>
> use something like Graal’s native image as a final condenser.<br>
<br>
Exactly.<br>
<br>
> ...<br>
> <br>
>> Some of these techniques might not require any specification changes, e.g.,<br>
>> expanding dynamic-proxy call sites into ordinary bytecode prior to run time.<br>
> <br>
> My experiments in this area have shown that the specification doesn’t need<br>
> to change, but that there are user-visible changes when doing this (ie:<br>
> Class:getNestMembers and others).  Is there an intention to document the<br>
> user visible aspects of changes from Condensers?<br>
<br>
To the extent that a condenser changes the behavior of a program within<br>
the bounds of the (possibly enhanced) Platform Specification then yes,<br>
we should document those changes.<br></blockquote><div><br></div><div>Ok. So user visible changes are in bounds for condensers provided they're well documented.  Good!</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>
>> Others will definitely require specification changes, e.g., resolving classes<br>
>> prior to run time. Yet others will take the form of new platform features<br>
>> that allow developers to express temporal shifting directly in source code,<br>
>> e.g., lazy static final fields.<br>
> <br>
> Glad to hear that language changes are in the scope of this proposal.<br>
> Helping developers say what they mean makes it easier to reason about what<br>
> needs to change versus trying to impose new semantics on top of the soup<br>
> that is <clinit>.<br>
<br>
Indeed!  Applying new semantics to existing code always leads to tears.<br>
<br>
>> So let’s generalize, and allow an arbitrary number of phases in which<br>
>> time-shifting transformations and related optimizations can be applied.<br>
> <br>
> To confirm: this is saying that a “condensed” Java application may act as<br>
> an input to a later phase of “condensation”?<br>
<br>
Yes, for some but likely not all definitions of “condensed.”  If you’ve<br>
condensed all the way down to a platform-specific executable, e.g., then<br>
it’s likely not worth the effort for us to support further condensation.<br>
(I suspect it’ll be acceptable to consider condensation to such formats<br>
to be terminal steps, as you suggest above.)<br></blockquote><div><br></div><div>A CRIU-based checkpoint is another such potential terminal format.  We're on the same page that not all condensation has to happen in one go - it's valid to have multiple kicks at the can provided a previous attempt wasn't terminal.</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>
>> Condensation is meaning preserving.<br>
> <br>
> Have you given thought to precisely specifying and then validating this<br>
> property?  It’s definitely something we want but it may be challenging to<br>
> enforce….<br>
<br>
The meaning of a Java program is already given by the Specification, and<br>
the JCK already validates a Java implementation by running a large<br>
collection of Specification-derived tests.  My initial thought here is<br>
to extend the JCK to test a condenser by applying the condenser to each<br>
JCK test and then verifying that the condensed test still passes.  (To<br>
keep JCK run times tractable, do this in large batches.)<br></blockquote><div><br></div><div>That's a great starting point.  I hadn't considered using the JCKs in that way.</div><div><br></div><div>The devil will be in the details as there will be conflicts between the condenser's changes (make this module unmodifiable) and the test's expectations (redefine class X).  This approach also feels a bit weighted toward the end - a condenser can be developed, merged, and only later be discovered to conflict with the JCKs.  I've been trying to think of ways to bring this forward in the development process and to make it more open but the answer may be as it is today - lots of jtregs, clearly written specs, and the final check is done by the JCKs.</div><div><br></div><div>Let us know if there are ways others can help with validating the behaviour of condensers when running the JCKs.</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>
>> To ensure that condensers run code correctly, and transform and constrain<br>
>> code only in ways that preserve meaning, we must add the concept of<br>
>> condensers to the Java Platform Specification.<br>
> <br>
> I’m unclear reading this if the set of Condensers will be limited to what<br>
> an implementation chooses to provide or if others (frameworks) can provide<br>
> their own Condensers as well?<br>
<br>
(See above.)<br>
<br>
> Currently, implementing a jlink plugin from outside the platform is a pain<br>
> (though possible with enough –add-opens and reflective hacks) but I’d<br>
> prefer to see Condensers have a more supported api so the ecosystem can<br>
> extend the concept.<br>
<br>
Agreed.  We probably do want an open condenser API, though designing a<br>
good one will take considerable effort.  (We didn’t open the jlink<br>
plugin API because we knew that it wasn’t ready.)<br></blockquote><div><br></div><div>+1.  Sounds like we're in the same ballpark on this.</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>
>> We can, however, enable other Java implementations (e.g., some future version<br>
>> of the GraalVM native-image tool) to do so.<br>
> <br>
> This is prescient given the recent announcement that Graal CE is moving to<br>
> OpenJDK =)<br>
<br>
What a coincidence!<br>
<br>
>> Eliminate apparently-unused classes and class members (i.e., stripping, which<br>
>> requires the constraint that selected classes and members cannot be reflected<br>
>> upon)<br>
> <br>
> Being slightly pedantic, it means the removed members can’t be reflected<br>
> on, correct?<br>
<br>
Yes, but ...<br>
<br>
>               A class that’s been stripped of unused methods / fields can<br>
> still have its remaining members reflectively looked up is my assumption.<br>
<br>
That’s a reasonable assumption.<br>
<br>
In detail, though, we could in principle retain reflective metadata even<br>
for removed program elements, if there’s a need to do so.  We could,<br>
likewise, remove reflective metadata for some retained program elements<br>
if we’re confident that those elements will never be reflected upon.<br>
More exploration required ...<br></blockquote><div><br></div><div>That makes sense.  If I'm following that correctly, we can mark some classes as "reflection hostile" and others as supporting reflection of all members (even the removed ones).  What I'm really hearing is a willingness to completely change the model so users can make different tradeoffs.  Very excited by this approach!</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>
>> jlink<br>
> <br>
> Using jlink is the natural starting point for this work.  It would be<br>
> unfortunate if condensers were limited to only work on modules given the<br>
> (unfortunately) slow update of them.  Is the intention to extend jlink to<br>
> work with classpath entities (ie: non-modular code) as well?  We foresee<br>
> the need for condensers to be able to “condense” non-modules as well.<br>
<br>
The jlink tool doesn’t support arbitrary class path code, or automatic<br>
modules, in order to guarantee that the resulting image is structurally<br>
correct by construction.  I’m reluctant to give up on that guarantee.<br>
Viable workarounds exist for non-modular code (jdeps, ModiTect, etc.),<br>
so developers who want to risk building a potentially-broken image from<br>
a potentially-broken class path can do so, at their option.<br></blockquote><div><br></div><div>Libraries are always the challenge here. Modularizing before your dependencies is difficult and while Leyden may help drive modularization in the ecosystem (a plus!), I hope we can take a pragmatic approach and bring class path code into Leyden fold.  As you said above, lot's to explore here but I ask that we add an explicit goal to bring class path code in as much as we can.</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>
I do expect that, in Leyden, we’ll find interesting ways to leverage the<br>
constraints already imposed by modules.  Hopefully that will motivate<br>
the further adoption of modules.<br>
<br>
> We’re excited to start working with you on this approach.  When do you<br>
> think we’d be ready to create a Leyden repo and start developing the code<br>
> for this approach?<br>
<br>
I’m in the process of setting up a repo; more on that soon.<br>
<br>
- Mark</blockquote><div><br></div><div>Thanks Mark!</div><div><br></div><div>--Dan </div></div></div>