RFR: 8194759: Support caching class mirror objects

coleen.phillimore at oracle.com coleen.phillimore at oracle.com
Wed Feb 21 01:40:28 UTC 2018


http://cr.openjdk.java.net/~jiangli/8194759/webrev.00/src/hotspot/share/oops/instanceKlass.cpp.frames.html

1299 void InstanceKlass::do_nonstatic_fields(void f(fieldDescriptor*, 
Handle, TRAPS), Handle mirror, TRAPS) {

Is this function only for iterating over the non-static fields in the 
mirror?   Can you write a comment above it saying this and why/when you 
iterate over nonstatic fields in the mirror?  Should it be #ifdef 
INCLUDE_CDS_JAVA_HEAP ?

http://cr.openjdk.java.net/~jiangli/8194759/webrev.00/src/hotspot/share/oops/klass.cpp.frames.html

581 // No GC barrier
582 void Klass::set_archived_java_mirror_raw(oop m) {
583 assert(DumpSharedSpaces, "called only during runtime");
584 _java_mirror = 
OopHandle((oop*)((uintptr_t)oopDesc::encode_heap_oop(m)));
  585 }

This doesn't seem right.  encode_heap_oop returns a narrowOop (if 
compressed oops).  Oh, I get it.  I don't really like the abuse of 
OopHandle type this way.

Can you make the mirror a union like:

    union mirror {
        OopHandle _java_mirror;
        narrowOop _archived_mirror;
   };

and avoid the casts.  Then it would be clear what is happening.   It 
also seems like Klass has some gaps at the end that you could put this 
temporary field in.

http://cr.openjdk.java.net/~jiangli/8194759/webrev.00/src/hotspot/share/classfile/javaClasses.cpp.frames.html

nit, can you put a comment on the end of the #if block?

953 #if INCLUDE_CDS_JAVA_HEAP
...

1202 #endif  // INCLUDE_CDS_JAVA_HEAP


Otherwise, this looks very good!

thanks,
Coleen

On 2/8/18 6:59 PM, Jiangli Zhou wrote:
> Please review the change for caching class mirror objects in of CDS archive. Currently, CDS archive contains java.lang.String objects and constant pool resolved_references arrays with resolved string constants (when archiving java heap object is allowed). This change adds the mirror objects. Please see the description below for details.
>
> RFE: https://bugs.openjdk.java.net/browse/JDK-8194759 <https://bugs.openjdk.java.net/browse/JDK-8194759>
> webrev: http://cr.openjdk.java.net/~jiangli/8194759/webrev.00/ <http://cr.openjdk.java.net/~jiangli/8194759/webrev.00/>
>
> Tested with all CDS/AppCDS tests (including the new tests added as part of the webrev), hs tier1 - hs tier6 (some of the tiers are in progress).
>
>
> Goal
> ====
> Support caching the klass mirror objects (java.lang.Class instances) for archived classes from built-in class loaders at CDS dump time. Runtime can use the cached mirrors without recreating the objects in the java heap.
> Classes with cached mirrors are not pre-initialized at dump time. Pre-initialization is not a goal in current scope.
> Support G1 GC, 64-bit (non-Windows). Requires UseCompressedOops and UseCompressedClassPointers.
>
> Archiving Mirror Objects at CDS Dump Time
> ==================================
> Mirror objects are copied to the 'open archive' heap regions at CDS dump time after class metadata is relocated to the shared archive spaces. In JDK 11, mirrors for archived classes with the built-in loaders (boot, PlatformClassLoader, AppClassLoader) can be archived. Following class mirrors are not archived:
>   * Archived classes with user defined class loaders
>   * Classes with signers (loaded from signed JAR file)
> The _java_mirror in the archived Klass is reset to NULL if the mirror object is not archived.
> If archiving java heap objects cannot be supported at current dumping time (e.g. unsupported GC is used), all archived Klass' _java_mirror handles are cleared and set to NULL.
>
> Mirrors for InstanceKlasses and arrayKlasses
> ————————————————————
> Mirror objects are scrubbed to remove all unsharable field values, including fields updated due to the execution of class initializer or other java code when writing out to the archive file. The cached mirrors are in the state of "being just created" by java_lang_Class::create_mirror() without the unsharable parts (e.g. class_loader, protection_domain, and module, etc.).
> The process for archiving mirrors for InstanceKlass and arrayKlass:
> 	• Allocate and copy the mirror data to the open archive heap region. The oopDesc::_metadata._klass in the archived mirror is updated to point to the relocated java.lang.Class Klass.
> 	• Clear all non-static fields in the archived mirror
> 	• For arrayKlass only
> 		• Archive the component klass mirror object and update the comp_mirror field
> 	• For InstanceKlass only
> 		• Reload initial values for all local static final fields. If the initial value is a String object, the String object is archived. For any of the static fields without initial value, the field in the archived mirror is set to 0/NULL.
> 		• The init_lock object is not archived and the field in the archived mirror is reset to NULL
> 		• Clear the protection_domain field in the archived mirror
> 	• Clear the class_loader field in the archived mirror
> 	• Clear the module field in the archived mirror
> 	• Relocate the _klass reference in the archived mirror to point to the archived Klass
> 	• Relocate the _array_klass reference in the archived mirror to point to the archived arrayKlass if not NULL
> 	• Update the klass _java_mirror handle to point to the archived mirror
> 	• Set _has_raw_archived_mirror flag in the archived class
>
> Mirrors for Primitive Types
> ————————————
> The mirrors for primitive types are created differently (see java_lang_Class::create_basic_type_mirror). All primitive type mirrors except T_VOID mirror have the _array_klass field initialized to corresponding TypeArrayKlass. The 'module' fields in basic type mirrors point to the java.base Module, which is set by ModuleEntryTable::patch_javabase_entries() when java.base Module is known.
> At dump time, the primitive type mirrors are copied to the open archive heap region. The _array_klass field in the archived mirror is updated to point to the relocated TypeArrayKlass. The 'module' field is cleared and set to NULL.
> All primitive type mirrors do not have associated 'Klass' metadata. The roots to primitive type mirrors are maintained by the Universe. When writing out the archive, the pointers to the primitive type mirrors are written into the archive.
>
> Restoring Mirror Objects at Runtime
> ============================
>
> Restoring Primitive Type Mirrors
> ——————————————
> The archived primitive mirrors are used at runtime without recreating. No restoration is needed for the primitive type mirrors. The pointers to the archived primitive type mirrors are reloaded into Universe during VM initialization. GC Access API (RootAccess<IN_ARCHIVE_ROOT>::oop_store()) is used when installing the primitive type mirrors in Universe. The mirror 'module' field is set by ModuleEntryTable::patch_javabase_entries() when java.base Module becomes known.
>
> Restoring InstanceKlass and ArrayKlass Mirrors
> ——————————————————————
> Mirror objects for non-primitive types are restored when shared classes are loaded and restored at runtime.
> Mirror restoration process:
> 	• For InstanceKlass mirror only
> 		• Create init_lock
> 		• Set protection_domain domain in the mirror
> 	• Set class_loader filed in the mirror
> 	• Create a handle for the mirror and set _java_mirror in the shared klass
> 	• Clear the _has_raw_archived_mirror flag in the shared klass
> 	• Set the module field in the mirror
>
> Mirror Fixup and Module Fixup
> ——————————————
> java.lang.Class field offsets (used by JVM) are cached at CDS dump time and loaded from the archive at runtime time. Shared classes loaded before java.lang.Class are not pushed onto the fixup_mirror_list. For those shared classes, the archived mirrors are restored directly when the classes are loaded.
> The mirrors are added to the fixup_module_list before java.base is defined and patched later when the java.lang.Module for java.base is known.
>
> GC Considerations
> ===============
> When an archived mirror is installed (becomes 'in use') during shared class loading and restoration at runtime, the archived mirror is accessed via GC access API with barrier. The archived object is denoted with IN_ARCHIVE_ROOT and becomes a special root that handled differently by GC and enqueued in SATB implicitly in G1.
> Similar to the klass constant pool resolved_references array, the archived mirrors resides in the 'open archive' heap region. The mirror fields may be updated with references pointing to other non-archive heap regions during runtime execution. References within the archived mirrors are scanned and followed by GC.
> Shared classes from builtin loaders are never unloaded after they become 'in use' (loaded from the archive) at runtime, which keeps all 'used' archived mirrors alive after being installed.
>
> Class Redefinitiaon/Restransformation with Archived Mirrors
> ==============================================
> In VM_RedefineClasses::redefine_single_class(), the mirror from ‘scratch_class' is not copied to ‘the_class’. After redefinition/retransformation, the original mirror in 'the_class' is still used.
>
> During verification of the scratch class, the original mirror (handle) from ‘the_class’ is temporary copied into the ‘scratch_class’ to avoid issues. When verification is done, the ‘scratch_class’ is restored to point to the scratch mirror.
>
> Class redefinition/retransformation has no impact on the archived mirror from the original class.
>
> Thanks!
>
> Jiangli



More information about the hotspot-runtime-dev mailing list