JDK-5002268 : Allow class sharing use with RedefineClasses
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 5.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2004-02-25
  • Updated: 2015-01-29
  • Resolved: 2006-06-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b86Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
This is a follow on to 4988776 which provided the interface changes to allow class sharing to be used with RedefineClasses.  This bug is to implement that functionality in the Reference Implementation.

Comments
SUGGESTED FIX See the attached 5002268-webrev-cr2-full.tgz file for the proposed fix that was sent out for code review round 2. See the attached 5002268-webrev-cr2-delta.tgz for just the deltas between round 1 and round 2.
24-05-2006

SUGGESTED FIX See the attached 5002268-webrev-cr1-full.tgz file for the proposed fix that was sent out for code review round 1. See the attached 5002268-webrev-cr1-delta.tgz for just the deltas between round 0 and round 1.
23-05-2006

SUGGESTED FIX See the attached 5002268-webrev-cr0.tgz file for the proposed fix that was sent out for code review round 0.
17-05-2006

EVALUATION Tom has recommended investigating a much less intrusive approach. I'm paraphrasing here: If RedefineClasses() is asked to redefine a shared class, then remap the shared readonly space to shared readwrite, private. This will allow RedefineClasses() to make its changes and still retain most of the benefits of sharing for classes that have not been redefined. For Solaris and Linux, mmap() semantics will allow us to remap the shared readonly space into a shared readwrite, private space "in place", i.e., without unmapping. The Win32 APIs may not allow us to do this so we may have to unmap and then remap. If that is the case, then there will be a small window between the unmap and remap where an access of the original shared space will fail. We can mitigate most of that risk by doing the remapping at a safepoint. Access to the original shared space by native code remains a risk.
09-05-2006

EVALUATION The shared heap consists of four regions: enum { ro = 0, // read-only shared space in the heap rw = 1, // read-write shared space in the heap md = 2, // miscellaneous data for initializing tables, etc. mc = 3, // miscellaneous code - vtable replacement. n_regions = 4 }; The shared klassOops/instanceKlasses live in the read-write space in the shared heap. An instanceKlass has 20 fields containing a total of 21 oops and some of those oops refer to oopArrays and some of these oops have their own embedded oops: public: oop* oop_block_beg() const { return adr_array_klasses(); } oop* oop_block_end() const { return adr_methods_default_annotations() + 1; } enum { implementors_limit = 2 // how many implems can we track? }; protected: // // The oop block. See comment in klass.hpp before making changes. // // Array classes holding elements of this class. klassOop _array_klasses; // Method array. objArrayOop _methods; // Int array containing the original order of method in the class file (for // JVMTI). typeArrayOop _method_ordering; // Interface (klassOops) this class declares locally to implement. objArrayOop _local_interfaces; // Interface (klassOops) this class implements transitively. objArrayOop _transitive_interfaces; // Instance and static variable information, 5-tuples of shorts [access, name // index, sig index, initval index, offset]. typeArrayOop _fields; // Constant pool for this class. constantPoolOop _constants; // Class loader used to load this class, NULL if VM loader used. oop _class_loader; // Protection domain. oop _protection_domain; // Class signers. objArrayOop _signers; // Name of source file containing this klass, NULL if not specified. symbolOop _source_file_name; // the source debug extension for this klass, NULL if not specified. symbolOop _source_debug_extension; // inner_classes attribute. typeArrayOop _inner_classes; // Implementors of this interface (not valid if it overflows) klassOop _implementors[implementors_limit]; // Generic signature, or null if none. symbolOop _generic_signature; // Annotations for this class, or null if none. typeArrayOop _class_annotations; // Annotation objects (byte arrays) for fields, or null if no annotations. // Indices correspond to entries (not indices) in fields array. objArrayOop _fields_annotations; // Annotation objects (byte arrays) for methods, or null if no annotations. // Index is the idnum, which is initially the same as the methods array index. objArrayOop _methods_annotations; // Annotation objects (byte arrays) for methods' parameters, or null if no // such annotations. // Index is the idnum, which is initially the same as the methods array index. objArrayOop _methods_parameter_annotations; // Annotation objects (byte arrays) for methods' default values, or null if no // such annotations. // Index is the idnum, which is initially the same as the methods array index. objArrayOop _methods_default_annotations; // // End of the oop block. // Some of these oops live in the read-write space and the rest live in the read-only space. At least one field, _methods, lives in the read-write space, but has an embedded oop field (a constMethodOop) that is in the read-only space. In order to make an instanceKlass redefineable, it will have to be copied from the shared read-write space into the regular PermGen. The oops embedded in the instanceKlass that are in the shared read-write space will also have to be copied to the regular PermGen. The constMethodOops that live in the shared read-only space will have to the copied to the regular PermGen. Other oops from the shared read-only space may also have to be copied to the regular PermGen. Once all the oops have been copied from the shared spaces to the regular PermGen, then all references to those oops will have to be found and updated to refer to the PermGen copies. All this work is just for one instanceKlass. Now the work has to be repeated for any direct and indirect subclasses of the instanceKlass that was redefined that also live in the shared space. If an interface is redefined, there will also need to be some work done there. However, for an interface, the work will be more difficult since there isn't a subclass relationship between a class that implements an interface and the interface itself. This looks like a lot of "accounting" style work and this won't be fast.
05-05-2006

EVALUATION Customers of java.lang.instrument and JVMTI want this, so we should provide it. ###@###.### 2004-02-24 If the agent adds can_redefine_classes/can_redefine_any_class in the onload phase then sharing will be disabled and will not inhibit dynamic instrumentation. For late-binding agent sthen 6173571 has improved things so that can_redefine_classes can be added in the live phase. can_redefine_any_class can also be obtained in the live phase if sharing is disabled. So at this time the only remaining issue is the case of a late-binding agent that needs to instrument shared classes (essentially rt.jar). ###@###.### 2005-05-19 09:39:51 GMT
19-05-2005

PUBLIC COMMENTS This is a follow on to 4988776 which provided the interface changes to allow class sharing to be used with RedefineClasses. This bug is to implement that functionality in the Reference Implementation.
10-06-2004