RFR JDK-8232222: Set state to 'linked' when an archived class is restored at runtime
David Holmes
david.holmes at oracle.com
Fri May 22 02:06:14 UTC 2020
Hi Ioi, Jiangli,
On 22/05/2020 5:30 am, Ioi Lam wrote:
>
>
> On 5/19/20 5:22 PM, Jiangli Zhou wrote:
>> Hi Ioi,
>>
>> On Mon, May 18, 2020 at 10:15 PM Ioi Lam <ioi.lam at oracle.com
>> <mailto:ioi.lam at oracle.com>> wrote:
>> >
>> > Hi Jiangli,
>> >
>> > Thank you for posting the design proposal. As you probably know, we
>> have started a discussion for Project Leyden [1] to improve start-up
>> performance of the JDK. It looks like you proposal will touch upon
>> many of the topics that are also of interest in Leyden. I would
>> encourage you to participate in the discussion so we can find the best
>> way of moving forward.
>> >
>>
>> Yes, I've responded to Mark's call for discussion for Project Leyden
>> yesterday (see
>> https://mail.openjdk.java.net/pipermail/discuss/2020-May/005464.html).
>>
>> > Part of your proposal is a generally available heap snapshot
>> mechanism. I think it will be really useful in speeding up start-up. I
>> want to understand how it works. Given a very simple program:
>> >
>> > @Preserve class A {
>> > static final int A = B.B + 1;
>> > }
>> > @Preserve class B {
>> > static final int B = A.A + 1;
>> > }
>> > class App {
>> > public static void main(String args[]) {
>> > if (args[0].equals("A")) {
>> > System.out.println("A.A = " + A.A);
>> > System.out.println("B.B = " + B.B);
>> > } else {
>> > System.out.println("B.B = " + B.B);
>> > System.out.println("A.A = " + A.A);
>> > }
>> > }
>> > }
>> >
>> > $ java -cp . App A
>> > A.A = 2
>> > B.B = 1
>> > $ java -cp . App B
>> > B.B = 2
>> > A.A = 1
>> >
>> > As you can see, the values of A.A and B.B depends on the order of
>> execution. However, the heap snapshot can save only one possible set
>> of values.
>> >
>> > So let's assume we have saved {A.A=2, B.B=1}. If you run the program
>> like:
>> >
>> > $ java -cp . App B
>> > B.B = 1
>> > A.A = 2
>> >
>> > The output is not valid according to the current Java Language Spec.
>> >
>> > I think there are ways to solve this. For example, we could evolve
>> the JLS to introduce a new concept of "linking" an Java app. The can
>> allow the programmer to specify a set of classes to be
>> loaded/linked/initialized ahead-of-time. I think it will be best to
>> discuss such JLS changes in Leyden. It is important not just for class
>> loading, but also for the AOT compiler.
>> >
>>
>> Perhaps finding the answers to the following questions may help?
>>
>> * How often does the above pattern (similar to a circular
>> dependency) in the test code occur in practices (in JDK code and
>> application code)?
>> * Is that intentional or unintentional? Does the behavior difference
>> cause any unwanted side-effects from developer & user point of view?
>> * What's the timeline for the JLS changes?
>> * If the pattern is not common in practices, is it possible to solve
>> the problem incrementally by addressing common cases first and
>> deliver performance improvements, while addressing the needed JLS
>> changes in parallel (then add support for this type of use cases)?
>> An opt-in solution would make that possible.
>>
>> Glad to see Mark's initiation of project Leyden. Looking forward to
>> participate. Let's discuss more as part of the project.
>>
>
> HI Jiangli,
>
> The problem with <clinit> order exists even without circular dependency.
I'm getting a real sense of deja-vu here as I'm sure we discussed all
the issues around trying to archive the initialized state of classes
many years ago. :) That was problematic enough. The idea of trying to
capture mutable state in a reusable way is even trickier (in a
multi-threaded environment). Heap snapshots (does Persistent Java ring a
bell?) and VM suspend/resume mechanisms have been touted for nearly 25
years now. :) But this is probably best discussed in relation to Leyden
as we seem far off-topic wrt. just marking archived classes as linked.
Cheers,
David
-----
> Here's another example:
>
> class A {
> static int A = B.B + 1;
> }
> class B {
> static int B;
> }
> class App2 {
> public static void main(String args[]) {
> if (args[0].equals("A")) {
> System.out.println("A.A = " + A.A);
> B.B ++;
> System.out.println("B.B = " + B.B);
> } else {
> System.out.println("B.B = " + B.B);
> B.B ++;
> System.out.println("A.A = " + A.A);
> }
> }
> }
> $ java -cp . App2 A
> A.A = 1
> B.B = 1
> $ java -cp . App2 B
> B.B = 0
> A.A = 2
>
> If we save the states {A.A = 1, B.B = 0}, we will get unexpected results:
>
> $ java -cp . App2 B
> B.B = 0
> A.A = 1
>
> Ideally, people should write their classes carefully so the <clinit>
> methods produce the same results regardless of execution order. Or, at
> least classes should have the same behavior regardless of how their
> static fields are initialized. However, as shown by my second example,
> it's very easy to violate this.
>
> As I mentioned on [1], I think we need JLS changes so that we can "link"
> discrete classes into an application in a predictable way. Hopefully
> this will restrict the variability of runtime behavior. It will be
> easier to perform ahead-of-time optimization. It will also help
> programmers write less buggy code.
>
> Without spec changes, perhaps we can have an opt-in mechanism. This is
> the approach used by GraalVM/nativeimage. I am not sure how this can be
> introduced into the JDK, though, if it can lead to spec violation.
>
> One way to get around it might be to introduce a "warm up wrapper".
> Something that logically behaves like this:
>
> original execution app (using my second example):
>
> $ java -cp . App2 B
>
> "wrapped" execution:
>
> $ java -cp wrapper:. Wrapper B
>
> class Wrapper {
> public static void main(String args[]) throws Exception {
> // force classes to initialize in this order
> Class.forName("A");
> Class.forName("B");
> // execute the real app
> App2.main(args);
> }
> }
>
> $ java -cp . Wrapper A
> A.A = 1
> B.B = 1
> $ java -cp . Wrapper B
> B.B = 0
> A.A = 1
>
> Now we can archive the state of the heap just before App2.main is
> execution. Notice that the output is not the same as with the original
> App2 class. However, it produces predictable results that people can
> understand. We can think of the A/B/Wrapper classes are a single library
> that wants itself to be initialized in a certain way without application
> intervention.
>
> It's also important that the execution of Wrapper is independent of the
> environment, args, etc, so we know it will always yield the same result.
>
> If we accept that this model is legal/desirable, we can implement
> Wrapper in other ways (e.g., as a text file that specifies the order of
> class initialization, etc). I am not sure about annotations -- I don't
> know how <clinit> order can be specified with annotations.
>
> Thanks
> - Ioi
>
>
>
>
>
> [1] https://mail.openjdk.java.net/pipermail/discuss/2020-May/005470.html
>> Thanks!
>> Jiangli
>>
>> > Thanks
>> > - Ioi
>> >
>> > [1]
>> https://mail.openjdk.java.net/pipermail/discuss/2020-April/005429.html
>> >
>> >
>> >
>> > On 5/15/20 7:35 PM, Jiangli Zhou wrote:
>> >
>> > I'd like to resume the discussion on this topic (sorry for the long
>> delay) and seek early feedback on the Java Class Pre-resolution and
>> Pre-initialization Design Proposal. The proposal enhances the existing
>> Caching Java Heap Objects approach and provides more general support
>> to pre-initialize classes and preserve static field values for both
>> JDK classes and application classes (loaded by system class loader).
>> Using annotation to tag a class or field for pre-initialization was
>> suggested by others (probably including Ioi, David ..., if my memory
>> serves me correctly) during the Caching Java Heap Objects work, so
>> that part of the credit goes to them. I adopted that suggestion in the
>> proposal after comparing it to other alternatives, please see details
>> in the doc.
>> > I have a class pre-initialization/preservation prototype now that's
>> built on top of the JDK-8232222 change with JDK 11. Quick experiment
>> that applied the pre-initialization to ~100 JDK classes used during VM
>> startup time showed about ~2ms improvement on my linux x86 machine.
>> >
>> > From what I learned so far, developers do see benefits of class
>> pre-initialization and use it in practices. Any work in this area,
>> including making it easier to achieve class pre-initialization, is
>> welcomed by Java developers.
>> > Feedback on the proposal and steps/process to moving forward to
>> contributing to OpenJDK is appreciated.
>> > Best regards,
>> > Jiangli
>> >
>> >
>> > On Wed, Jan 8, 2020 at 3:10 PM Jiangli Zhou <jianglizhou at google.com
>> <mailto:jianglizhou at google.com>> wrote:
>> >>
>> >> Hi David,
>> >>
>> >> Thanks a lot for the inputs from JVMS compliance perspective!
>> >>
>> >> On Tue, Jan 7, 2020 at 10:02 PM David Holmes
>> <david.holmes at oracle.com <mailto:david.holmes at oracle.com>> wrote:
>> >> >
>> >> > Hi Jiangli,
>> >> >
>> >> > On 21/12/2019 11:50 am, Jiangli Zhou wrote:
>> >> > > Hi David,
>> >> > >
>> >> > > On Thu, Dec 19, 2019 at 7:43 PM David Holmes
>> <david.holmes at oracle.com <mailto:david.holmes at oracle.com>> wrote:
>> >> > >>
>> >> > >> Hi Jiangli,
>> >> > >>
>> >> > >> On 20/12/2019 1:01 pm, Jiangli Zhou wrote:
>> >> > >>> Hi Coleen,
>> >> > >>>
>> >> > >>> Thank you for your feedback! I was planning to ping you and
>> get your
>> >> > >>> opinion. Happy to see your comment and involvement!
>> >> > >>>
>> >> > >>> On Thu, Dec 19, 2019 at 2:26 PM <coleen.phillimore at oracle.com
>> <mailto:coleen.phillimore at oracle.com>> wrote:
>> >> > >>>>
>> >> > >>>>
>> >> > >>>>
>> >> > >>>> On 12/16/19 10:30 PM, Jiangli Zhou wrote:
>> >> > >>>>> Since this change involves security related issues, Ioi,
>> Claes and I
>> >> > >>>>> had off-mailing list discussion and initial code review
>> (thanks!).
>> >> > >>>>> Thanks Ioi for investigating and providing test cases in
>> security
>> >> > >>>>> related area. As the security related parts are settled,
>> I'd like to
>> >> > >>>>> resume the discussion and review in the open, and hope to
>> move this
>> >> > >>>>> forward.
>> >> > >>>>>
>> >> > >>>>> My initial change (webrev.00) set all archived classes
>> loaded by
>> >> > >>>>> builtin loaders in 'linked' state during restoration in
>> >> > >>>>> InstanceKlass::restore_unshareable_info(). Ioi demonstrated a
>> >> > >>>>> potential issue for classes loaded by the AppClassLoader
>> (thanks
>> >> > >>>>> again). More investigation and work are needed to handle
>> the general
>> >> > >>>>> case for AppClassLoader. Following are two proposals
>> provide the
>> >> > >>>>> support with narrower scopes with no potential security
>> issue. Option
>> >> > >>>>> (1) is an approach that I implemented in one of my earlier
>> patches.
>> >> > >>>>>
>> >> > >>>>> Option (1)
>> >> > >>>>> ========
>> >> > >>>>> Set an archived class in 'linked' state during restoration in
>> >> > >>>>> InstanceKlass::restore_unshareable_info() for the following
>> cases:
>> >> > >>>>>
>> >> > >>>>> Case 1): For an archived class loaded by the NULL class
>> loader by
>> >> > >>>>> default (when verification is not required for classes
>> loaded by the
>> >> > >>>>> NULL class loader, which is the default case).
>> >> > >>>>> Case 2): For an archived class loaded by the
>> PlatformClassLoader and
>> >> > >>>>> AppClassLoader when verification is disabled at runtime.
>> This use case
>> >> > >>>>> (disabling class verification) appears to be important in
>> some cases
>> >> > >>>>> for real world applications where verification can be
>> safely disabled.
>> >> > >>>>>
>> >> > >>>>> http://cr.openjdk.java.net/~jiangli/8232222/webrev.01/
>> >> > >>>>
>> >> > >>>> Hi Jiangli,
>> >> > >>>>
>> >> > >>>> We've deprecated -verify:none and I don't want to have the
>> JVM add any
>> >> > >>>> feature or an optimization in particular that uses this. I
>> don't think
>> >> > >>>> we should invite these bugs.
>> >> > >>>
>> >> > >>> Your feedback sound reasonable for options (1).
>> >> > >>>
>> >> > >>> Not completely related to this discussion, I have a
>> feedback/input
>> >> > >>> about -Xverify:none removal based on my observation of the flag
>> >> > >>> usages. -Xverify:none is useful for reducing performance overhead
>> >> > >>> caused by verification and users do enable it when it is safe and
>> >> > >>> performance is important. In some cases, there can be ~10%
>> performance
>> >> > >>> difference. For -Xverify:none removal, it would be important
>> to have a
>> >> > >>> good strategy on how and when to do so, at least after dynamic
>> >> > >>> archiving is completely mature, and ready for its prime time
>> and broad
>> >> > >>> adoptions.
>> >> > >>>
>> >> > >>>>
>> >> > >>>>>
>> >> > >>>>> Option (2)
>> >> > >>>>> ========
>> >> > >>>>> Set an archived class loaded by the NULL loader in 'linked'
>> state
>> >> > >>>>> during runtime restoration in
>> >> > >>>>> InstanceKlass::restore_unshareable_info() by default.
>> Option (2) only
>> >> > >>>>> supports the case (1) described in option (1).
>> >> > >>>>>
>> >> > >>>>> http://cr.openjdk.java.net/~jiangli/8232222/webrev.02/
>> >> > >>>>>
>> >> > >>>>> Both of the above proposals provide the performance benefit
>> described
>> >> > >>>>> in the original review request.
>> >> > >>>>>
>> >> > >>>>> In addition to the performance benefit, my other motivation
>> for this
>> >> > >>>>> change is to provide a foundation for potential
>> optimization with more
>> >> > >>>>> general class pre-initialization (currently only a few
>> special cases
>> >> > >>>>> are supported in the JDK classes) on top of the heap object
>> graph
>> >> > >>>>> archiving mechanism (, and constant pool field and method
>> references
>> >> > >>>>> pre-resolution) in the future. Apologize for not clearly
>> explain that
>> >> > >>>>> in the original review request, although the RFE was linked
>> to the
>> >> > >>>>> umbrella RFE for pre-initialization/pre-resolution. I've
>> clarified it
>> >> > >>>>> in the RFE as well.
>> >> > >>>>
>> >> > >>>> I've read the RFE for this and the umbrella RFE, but I don't
>> understand
>> >> > >>>> the design or how this would accomplish it. Could you have the
>> >> > >>>> initialized version of the class in the archive instead and
>> use it when
>> >> > >>>> we call klass->initialize() rather than calling into the
>> <clinit> function?
>> >> > >>>
>> >> > >>> It is a fine idea. If there is no JVMS compliance issue, we can
>> >> > >>> explore in this direction since it could be slightly more
>> efficient
>> >> > >>> (not observable). We still need to post JVMTI events for loading,
>> >> > >>> preparing, etc at runtime. Can we involve David H. for the Spec
>> >> > >>> related discussions?
>> >> > >>
>> >> > >> I'm always lurking :)
>> >> > >>
>> >> > >> I'm not clear what exactly is being proposed at this stage,
>> but I assume
>> >> > >> this is a discussion for a future RFE in the New Year.
>> >> > >
>> >> > > It's related to Coleen's proposal of 'preserving' an archived
>> class
>> >> > > in 'initialized' state at CDS dump time for cases that are
>> suitable.
>> >> > > Currently all archived classes are reset back to 'allocated'
>> state at
>> >> > > dump time. If a class' static fields have no dependency on runtime
>> >> > > context and can be safely pre-initialized at dump time, we can
>> >> > > potentially leave the class in 'initialized' state. At runtime, we
>> >> > > still need to do all the necessary operations for restoration but
>> >> > > without modifying the class state itself. It would be good to
>> have a
>> >> > > spec related discussion upfront so no work is wasted. My
>> feeling is it
>> >> > > doesn't violate the JVMS, but it's better to confirm it before the
>> >> > > actual implementation.
>> >> >
>> >> > The spec is very strict on when initialization must occur, there
>> is no
>> >> > option to be stricter or lazier. But if the initialized fields have
>> >> > idempotent values no matter when the initialization occurs then
>> the fact
>> >> > they already had that value won't be visible to any use of the class.
>> >> > However ...
>> >> >
>> >> > > We also need to make sure that we don't expose a class with an
>> >> > > 'inconsistent' state to a JVMTI agent before it's fully restored.
>> >> > > There was a JVMTI/CDS bug:
>> >> > > https://bugs.openjdk.java.net/browse/JDK-8210926. A JVMTI agent may
>> >> > > observe a class (from the ClassLoaderData::_klasses list)
>> before the
>> >> > > mirror is restored. So we would need to do some reordering in that
>> >> > > area if an archived class is preserved in 'initialized' state.
>> >> >
>> >> > ... you would need to be careful about not showing the class as
>> >> > initialized to tools, prior to when actual initialization should
>> occur
>> >> > as per the spec.
>> >>
>> >> Agreed, this approach could introduce potential complications for
>> >> JVMTI agents. It would need to be very carefully ordered to make sure
>> >> tools don't observe a class that's not completely linked (or
>> >> initialized) but with linked (or initialized) state. Keeping the class
>> >> state in 'allocated' in the archive effectively avoids the
>> >> complication.
>> >>
>> >> >
>> >> > One possibility may be to preserve the fields in the archive but
>> >> > maintain the class state as "linked" until initialization is
>> mandated,
>> >> > at which point you can just flip the state to "initialized" without
>> >> > needing to execute the <clinit> code.
>> >>
>> >> Since currently we still have some restoration work for the linking
>> >> part, would it be better to maintain the class state as 'allocated'
>> >> until runtime restoration? Restoration can flip the state to 'linked',
>> >> which avoids the complications for JVMTI agent.
>> >>
>> >> For the 'initialized' state, flipping it at the natural initialization
>> >> time of a class adds some complications and a small overhead to
>> >> field/method constant pool reference pre-resolving. I'll give some
>> >> more thoughts to that.
>> >>
>> >> Thanks again!
>> >>
>> >> Best,
>> >> Jiangli
>> >>
>> >> >
>> >> > Cheers,
>> >> > David
>> >> > -----
>> >> >
>> >> > > With that, some of the changes in my current webrev.02
>> >> > > (http://cr.openjdk.java.net/~jiangli/8232222/webrev.02/) may
>> still be
>> >> > > needed, but without the change for the '_init_state'.
>> >> > >
>> >> > > We can have more discussions after the holidays.
>> >> > >
>> >> > > Best,
>> >> > > Jiangli
>> >> > >
>> >> > >
>> >> > >>
>> >> > >> Cheers,
>> >> > >> David
>> >> > >>
>> >> > >>>>
>> >> > >>>> The JEP process is being streamlined more, so maybe this
>> work requires
>> >> > >>>> one. I only just dropped into this thread but I'd love to
>> learn more
>> >> > >>>> about it, but after the holidays. I have some concerns
>> about this code
>> >> > >>>> change. It seems innocuous enough but it's limited to the
>> >> > >>>> bootclassloader and I don't know how this will help.
>> >> > >>>
>> >> > >>> Ioi and I also briefly discussed about JEP process. Maybe we
>> could
>> >> > >>> break the work into a series of JEPs if necessary, so it
>> still enables
>> >> > >>> incremental developments? Each self-contained block of work
>> could be
>> >> > >>> mapped to an individual JEP. That would help us validate the
>> benefit
>> >> > >>> of each sub-work (of pre-resolution and pre-initialization)
>> in real
>> >> > >>> world production environment more efficiently, and give the
>> access to
>> >> > >>> these new improvements to OpenJDK users in the community more
>> quickly.
>> >> > >>> It would also help me streamline the private patches without
>> dealing
>> >> > >>> with a lot of code conflicts and reduce the cost/overhead of
>> >> > >>> maintaining the patches.
>> >> > >>>
>> >> > >>> I'd love to discuss more with you after the holidays. I will
>> also need
>> >> > >>> to do some more researches (about the process) on my side.
>> >> > >>>
>> >> > >>> Best regards,
>> >> > >>> Jiangli
>> >> > >>>
>> >> > >>>>
>> >> > >>>> Thanks,
>> >> > >>>> Coleen
>> >> > >>>>>
>> >> > >>>>> Following are more details on pre-initialization for interested
>> >> > >>>>> readers. I'm still investigating this area and flushing out the
>> >> > >>>>> details. So the best approach is to do those incrementally. The
>> >> > >>>>> information that I provide below may change. It is probably
>> better to
>> >> > >>>>> have a general pre-initialization and pre-resolving
>> discussion that's
>> >> > >>>>> separate from this review request. And we can move the
>> current change
>> >> > >>>>> forward once it's reviewed and accepted.
>> >> > >>>>>
>> >> > >>>>> One immediate improvement that the current change would
>> enable is
>> >> > >>>>> simplifying the existing static field pre-initialization
>> applied to
>> >> > >>>>> some of the JDK classes. When an archived class can be set
>> in the
>> >> > >>>>> 'linked' state during runtime restoration, it makes it
>> possible to
>> >> > >>>>> place the class in 'initialized' state at restoration. As
>> loading,
>> >> > >>>>> verifying, linking/preparing and initializing orders are
>> mandated by
>> >> > >>>>> JVMS, a class can only be placed in 'initialized' after it
>> is already
>> >> > >>>>> in 'linked' state. Also, we want to avoid a partially
>> initialized
>> >> > >>>>> class state. Currently when static fields for a given JDK
>> class is
>> >> > >>>>> pre-initialized at CDS dump time, we need to store the
>> preserved field
>> >> > >>>>> values separately from the class mirror object (j.l.Class
>> instance).
>> >> > >>>>> At runtime, during running the class' static initializer
>> (<clinit>),
>> >> > >>>>> the VM finds and stores the values back to the
>> corresponding static
>> >> > >>>>> fields in the mirror. Following is an example where we
>> pre-initialize
>> >> > >>>>> java.lang.module.Configuration. In the code below,
>> >> > >>>>> VM.initializeFromArchive() is called to retrieve the
>> preserved value
>> >> > >>>>> and store back to the mirror. A check is performed to
>> verify if the
>> >> > >>>>> value is restored from archive, otherwise we do runtime
>> >> > >>>>> initialization. The complication is due to the separate
>> storage for
>> >> > >>>>> the preserved values (stored outside the mirror).
>> >> > >>>>>
>> >> > >>>>> static {
>> >> > >>>>> // Initialize EMPTY_CONFIGURATION from the archive.
>> >> > >>>>> VM.initializeFromArchive(Configuration.class);
>> >> > >>>>>
>> >> > >>>>> // Create a new empty Configuration if there is
>> no archived version.
>> >> > >>>>> if (EMPTY_CONFIGURATION == null) {
>> >> > >>>>> EMPTY_CONFIGURATION = new Configuration();
>> >> > >>>>> }
>> >> > >>>>> }
>> >> > >>>>>
>> >> > >>>>> With the proposed change in the current review request, it
>> would
>> >> > >>>>> enable us to set Configuration in 'initialized' state
>> during runtime
>> >> > >>>>> restoration, and therefore allow us to preserve the static
>> field value
>> >> > >>>>> as part of the mirror without violating the mandated ordering
>> >> > >>>>> requirement. With that, we can eliminate the
>> >> > >>>>> VM.initializeFromArchive() call and the if check in the
>> Java code for
>> >> > >>>>> some of the use cases. Once Configuration is fully
>> 'restored' at
>> >> > >>>>> runtime, there is no need to execute the <clinit> at all.
>> It would
>> >> > >>>>> allow us to apply pre-initialization to more JDK classes if
>> desired,
>> >> > >>>>> without complicating the Java code.
>> >> > >>>>>
>> >> > >>>>> When we can properly set an archived class to 'initialized'
>> state at
>> >> > >>>>> restore time, it then will enable us to pre-resolve related
>> constant
>> >> > >>>>> pool method and field references.
>> >> > >>>>>
>> >> > >>>>> Ioi had some questions for pre-initialization and
>> pre-resolution which
>> >> > >>>>> I'm including below with my answers inlined. As I'm still
>> >> > >>>>> investigating this area, so most likely they are not final.
>> >> > >>>>>
>> >> > >>>>> - Are you going to do the same thing for the initialized
>> state -- all
>> >> > >>>>> classes loaded by boot loader will be automatically
>> initialized?
>> >> > >>>>>
>> >> > >>>>> By default, an archived class loaded by the boot loader
>> will only be
>> >> > >>>>> placed in 'linked' state at restoration time when it is
>> suitable. For
>> >> > >>>>> 'value' object that cannot be placed in 'linked' state at
>> restore time
>> >> > >>>>> when archiving supported for that is added in the future,
>> it can be
>> >> > >>>>> handled differently and the related class can remain in
>> 'alloced'
>> >> > >>>>> state during restoration.
>> >> > >>>>>
>> >> > >>>>> An archived class will only be set to 'initialized' during
>> runtime
>> >> > >>>>> restoration if the class can be in fully 'initialized'
>> state with all
>> >> > >>>>> static fields pre-initialized and preserved. An archived
>> class can be
>> >> > >>>>> 'flagged' for that case at dump time. Specific
>> implementation details
>> >> > >>>>> need further investigation.
>> >> > >>>>>
>> >> > >>>>> - That certainly doesn't seem feasible, so you will
>> probably need to
>> >> > >>>>> put some restrictions. So why aren't you putting in those
>> restrictions
>> >> > >>>>> now? Do you know what these restrictions are?
>> >> > >>>>>
>> >> > >>>>> The restriction only applies when we add support for more
>> general
>> >> > >>>>> 'pre-initialization' and 'value' object archiving.
>> Currently, for the
>> >> > >>>>> restore-time 'linked' state implementation in the webrevs, the
>> >> > >>>>> restriction does not apply.
>> >> > >>>>>
>> >> > >>>>> - Will they be so restrictive that this will not be practical?
>> >> > >>>>>
>> >> > >>>>> As pre-initialization cannot be applied to all cases,
>> selective and
>> >> > >>>>> targeted pre-initialization (following current CDS static field
>> >> > >>>>> pre-initializing model) is a more flexible approach that
>> provides both
>> >> > >>>>> performance benefits and JVMS/language spec compliant.
>> >> > >>>>>
>> >> > >>>>> Comments are welcome and appreciated!
>> >> > >>>>>
>> >> > >>>>> Best regards,
>> >> > >>>>> Jiangli
>> >> > >>>>>
>> >> > >>>>>
>> >> > >>>>>
>> >> > >>>>>
>> >> > >>>>> On Thu, Nov 28, 2019 at 9:33 AM Jiangli Zhou
>> <jianglizhou at google.com <mailto:jianglizhou at google.com>> wrote:
>> >> > >>>>>> Hi,
>> >> > >>>>>>
>> >> > >>>>>> Please review the following optimization related to
>> archived classes'
>> >> > >>>>>> (from builtin loaders) runtime restoration and linking. It
>> is not
>> >> > >>>>>> intended for OpenJDK 14. After reviewers review the
>> change, I'll wait
>> >> > >>>>>> for 14 fork before pushing.
>> >> > >>>>>>
>> >> > >>>>>> webrev: http://cr.openjdk.java.net/~jiangli/8232222/webrev.00/
>> >> > >>>>>> RFE: https://bugs.openjdk.java.net/browse/JDK-8232222
>> >> > >>>>>>
>> >> > >>>>>> Motivation and details of the change, which are duplicated
>> in the RFE
>> >> > >>>>>> =====================================================
>> >> > >>>>>>
>> >> > >>>>>> When linking a class, InstanceKlass::link_class_impl()
>> first links all
>> >> > >>>>>> super classes and super interfaces of the current class.
>> For the
>> >> > >>>>>> current class, it then verifies and rewrites the bytecode,
>> links
>> >> > >>>>>> methods, initializes the itable and vtable, and sets the
>> current class
>> >> > >>>>>> to 'linked' state.
>> >> > >>>>>>
>> >> > >>>>>> When loading an archived class at runtime,
>> >> > >>>>>> SystemDictionary::load_shared_class makes sure the super
>> types (all
>> >> > >>>>>> super classes and super interfaces) in the class hierarchy
>> are loaded
>> >> > >>>>>> first. If not, the archived class is not used. The
>> archived class is
>> >> > >>>>>> restored when 'loading' from the archive. At the end of the
>> >> > >>>>>> restoration, all methods are linked. As bytecode
>> verification and
>> >> > >>>>>> rewriting are done at CDS dump time, the runtime does not
>> redo the
>> >> > >>>>>> operations for an archived class.
>> >> > >>>>>>
>> >> > >>>>>> If we make sure the itable and vtable are properly
>> initialized (not
>> >> > >>>>>> needed for classes loaded by the NULL class loader) and
>> >> > >>>>>> SystemDictionaryShared::check_verification_constraints is
>> performed
>> >> > >>>>>> for an archived class during restoration, then the
>> archived class
>> >> > >>>>>> (from builtin loaders) is effectively in 'linked' state.
>> >> > >>>>>>
>> >> > >>>>>> For all archived classes loaded by the builtin loaders, we
>> can safely
>> >> > >>>>>> set to 'linked' state at the end of restoration. As a
>> result, we can
>> >> > >>>>>> save the work for iterating the super types in
>> >> > >>>>>> InstanceKlass::link_class_impl() at runtime.
>> >> > >>>>>>
>> >> > >>>>>> Performance results
>> >> > >>>>>> ================
>> >> > >>>>>>
>> >> > >>>>>> With both JDK 11 and the latest jdk/jdk, the proposed
>> change saves
>> >> > >>>>>> ~1.5M instruction execution when running HelloWorld with
>> the default
>> >> > >>>>>> CDS. Please see raw data in the RFE. For applications
>> using more
>> >> > >>>>>> archived classes at runtime, larger saving should be
>> experienced.
>> >> > >>>>>>
>> >> > >>>>>> Testing
>> >> > >>>>>> ======
>> >> > >>>>>> Tested with all jtreg cds/* tests, which include all
>> appcds tests.
>> >> > >>>>>> Submit repo testing passed.
>> >> > >>>>>>
>> >> > >>>>>> The change has also gone through internal testing with
>> very large
>> >> > >>>>>> number of tests (all with default CDS enabled) for more
>> than a month.
>> >> > >>>>>>
>> >> > >>>>>> Best,
>> >> > >>>>>> Jiangli
>> >> > >>>>
>> >
>> >
>
More information about the hotspot-runtime-dev
mailing list