RFR JDK-8232222: Set state to 'linked' when an archived class is restored at runtime

Jiangli Zhou jianglizhou at google.com
Wed May 27 01:21:37 UTC 2020


On Thu, May 21, 2020 at 7:06 PM David Holmes <david.holmes at oracle.com> wrote:
>
> 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.
>

Agreed with David here. It's the best to leave the class-init ordering
issues and possible solutions to Leyden discussions. Finding answers
to the questions in my previous email may help, I hope.

Focusing on the link state for archived classes in this thread, I
updated the webrev to only set archived boot classes to 'linked' state
at restore time. More investigations can be done for archived classes
for other builtin loaders.

  http://cr.openjdk.java.net/~jiangli/8232222/webrev.02/

Please let me know if there is any additional concerns to the change.

Best regards,
Jiangli

> 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