Mercurial > hg > graal-jvmci-8
comparison src/share/vm/prims/jvmtiRedefineClasses.cpp @ 10268:43083e670adf
8005056: NPG: Crash after redefining java.lang.Object
Summary: Need to walk array class vtables replacing old methods too if j.l.o redefined
Reviewed-by: sspitsyn, dcubed, ctornqvi
author | coleenp |
---|---|
date | Mon, 13 May 2013 15:37:08 -0400 |
parents | 712a1e9c91f3 |
children | e7d29a019a3c |
comparison
equal
deleted
inserted
replaced
10267:8b40495b9381 | 10268:43083e670adf |
---|---|
158 // always called for non-product bits. | 158 // always called for non-product bits. |
159 #ifdef PRODUCT | 159 #ifdef PRODUCT |
160 if (RC_TRACE_ENABLED(0x00004000)) { | 160 if (RC_TRACE_ENABLED(0x00004000)) { |
161 #endif | 161 #endif |
162 RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class")); | 162 RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class")); |
163 SystemDictionary::classes_do(check_class, thread); | 163 CheckClass check_class(thread); |
164 ClassLoaderDataGraph::classes_do(&check_class); | |
164 #ifdef PRODUCT | 165 #ifdef PRODUCT |
165 } | 166 } |
166 #endif | 167 #endif |
167 } | 168 } |
168 | 169 |
2651 rewrite_cp_refs_in_stack_map_table(method, THREAD); | 2652 rewrite_cp_refs_in_stack_map_table(method, THREAD); |
2652 } // end for each method | 2653 } // end for each method |
2653 } // end set_new_constant_pool() | 2654 } // end set_new_constant_pool() |
2654 | 2655 |
2655 | 2656 |
2656 void VM_RedefineClasses::adjust_array_vtable(Klass* k_oop) { | |
2657 ArrayKlass* ak = ArrayKlass::cast(k_oop); | |
2658 bool trace_name_printed = false; | |
2659 ak->vtable()->adjust_method_entries(_matching_old_methods, | |
2660 _matching_new_methods, | |
2661 _matching_methods_length, | |
2662 &trace_name_printed); | |
2663 } | |
2664 | |
2665 // Unevolving classes may point to methods of the_class directly | 2657 // Unevolving classes may point to methods of the_class directly |
2666 // from their constant pool caches, itables, and/or vtables. We | 2658 // from their constant pool caches, itables, and/or vtables. We |
2667 // use the SystemDictionary::classes_do() facility and this helper | 2659 // use the ClassLoaderDataGraph::classes_do() facility and this helper |
2668 // to fix up these pointers. | 2660 // to fix up these pointers. |
2669 // | 2661 |
2670 // Note: We currently don't support updating the vtable in | 2662 // Adjust cpools and vtables closure |
2671 // arrayKlassOops. See Open Issues in jvmtiRedefineClasses.hpp. | 2663 void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { |
2672 void VM_RedefineClasses::adjust_cpool_cache_and_vtable(Klass* k_oop, | 2664 |
2673 ClassLoaderData* initiating_loader, | 2665 // This is a very busy routine. We don't want too much tracing |
2674 TRAPS) { | 2666 // printed out. |
2675 Klass *k = k_oop; | 2667 bool trace_name_printed = false; |
2676 if (k->oop_is_instance()) { | 2668 |
2677 HandleMark hm(THREAD); | 2669 // Very noisy: only enable this call if you are trying to determine |
2678 InstanceKlass *ik = (InstanceKlass *) k; | 2670 // that a specific class gets found by this routine. |
2671 // RC_TRACE macro has an embedded ResourceMark | |
2672 // RC_TRACE_WITH_THREAD(0x00100000, THREAD, | |
2673 // ("adjust check: name=%s", k->external_name())); | |
2674 // trace_name_printed = true; | |
2675 | |
2676 // If the class being redefined is java.lang.Object, we need to fix all | |
2677 // array class vtables also | |
2678 if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) { | |
2679 k->vtable()->adjust_method_entries(_matching_old_methods, | |
2680 _matching_new_methods, | |
2681 _matching_methods_length, | |
2682 &trace_name_printed); | |
2683 } else if (k->oop_is_instance()) { | |
2684 HandleMark hm(_thread); | |
2685 InstanceKlass *ik = InstanceKlass::cast(k); | |
2679 | 2686 |
2680 // HotSpot specific optimization! HotSpot does not currently | 2687 // HotSpot specific optimization! HotSpot does not currently |
2681 // support delegation from the bootstrap class loader to a | 2688 // support delegation from the bootstrap class loader to a |
2682 // user-defined class loader. This means that if the bootstrap | 2689 // user-defined class loader. This means that if the bootstrap |
2683 // class loader is the initiating class loader, then it will also | 2690 // class loader is the initiating class loader, then it will also |
2693 InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; | 2700 InstanceKlass::cast(_the_class_oop)->class_loader() != NULL; |
2694 if (is_user_defined && ik->class_loader() == NULL) { | 2701 if (is_user_defined && ik->class_loader() == NULL) { |
2695 return; | 2702 return; |
2696 } | 2703 } |
2697 | 2704 |
2698 // If the class being redefined is java.lang.Object, we need to fix all | |
2699 // array class vtables also | |
2700 if (_the_class_oop == SystemDictionary::Object_klass()) { | |
2701 ik->array_klasses_do(adjust_array_vtable); | |
2702 } | |
2703 | |
2704 // This is a very busy routine. We don't want too much tracing | |
2705 // printed out. | |
2706 bool trace_name_printed = false; | |
2707 | |
2708 // Very noisy: only enable this call if you are trying to determine | |
2709 // that a specific class gets found by this routine. | |
2710 // RC_TRACE macro has an embedded ResourceMark | |
2711 // RC_TRACE_WITH_THREAD(0x00100000, THREAD, | |
2712 // ("adjust check: name=%s", ik->external_name())); | |
2713 // trace_name_printed = true; | |
2714 | |
2715 // Fix the vtable embedded in the_class and subclasses of the_class, | 2705 // Fix the vtable embedded in the_class and subclasses of the_class, |
2716 // if one exists. We discard scratch_class and we don't keep an | 2706 // if one exists. We discard scratch_class and we don't keep an |
2717 // InstanceKlass around to hold obsolete methods so we don't have | 2707 // InstanceKlass around to hold obsolete methods so we don't have |
2718 // any other InstanceKlass embedded vtables to update. The vtable | 2708 // any other InstanceKlass embedded vtables to update. The vtable |
2719 // holds the Method*s for virtual (but not final) methods. | 2709 // holds the Method*s for virtual (but not final) methods. |
2720 if (ik->vtable_length() > 0 && ik->is_subtype_of(_the_class_oop)) { | 2710 if (ik->vtable_length() > 0 && ik->is_subtype_of(_the_class_oop)) { |
2721 // ik->vtable() creates a wrapper object; rm cleans it up | 2711 // ik->vtable() creates a wrapper object; rm cleans it up |
2722 ResourceMark rm(THREAD); | 2712 ResourceMark rm(_thread); |
2723 ik->vtable()->adjust_method_entries(_matching_old_methods, | 2713 ik->vtable()->adjust_method_entries(_matching_old_methods, |
2724 _matching_new_methods, | 2714 _matching_new_methods, |
2725 _matching_methods_length, | 2715 _matching_methods_length, |
2726 &trace_name_printed); | 2716 &trace_name_printed); |
2727 } | 2717 } |
2733 // every InstanceKlass that has an itable since there isn't a | 2723 // every InstanceKlass that has an itable since there isn't a |
2734 // subclass relationship between an interface and an InstanceKlass. | 2724 // subclass relationship between an interface and an InstanceKlass. |
2735 if (ik->itable_length() > 0 && (_the_class_oop->is_interface() | 2725 if (ik->itable_length() > 0 && (_the_class_oop->is_interface() |
2736 || ik->is_subclass_of(_the_class_oop))) { | 2726 || ik->is_subclass_of(_the_class_oop))) { |
2737 // ik->itable() creates a wrapper object; rm cleans it up | 2727 // ik->itable() creates a wrapper object; rm cleans it up |
2738 ResourceMark rm(THREAD); | 2728 ResourceMark rm(_thread); |
2739 ik->itable()->adjust_method_entries(_matching_old_methods, | 2729 ik->itable()->adjust_method_entries(_matching_old_methods, |
2740 _matching_new_methods, | 2730 _matching_new_methods, |
2741 _matching_methods_length, | 2731 _matching_methods_length, |
2742 &trace_name_printed); | 2732 &trace_name_printed); |
2743 } | 2733 } |
2756 // updated. We can simply start with the previous version(s) in | 2746 // updated. We can simply start with the previous version(s) in |
2757 // that case. | 2747 // that case. |
2758 constantPoolHandle other_cp; | 2748 constantPoolHandle other_cp; |
2759 ConstantPoolCache* cp_cache; | 2749 ConstantPoolCache* cp_cache; |
2760 | 2750 |
2761 if (k_oop != _the_class_oop) { | 2751 if (ik != _the_class_oop) { |
2762 // this klass' constant pool cache may need adjustment | 2752 // this klass' constant pool cache may need adjustment |
2763 other_cp = constantPoolHandle(ik->constants()); | 2753 other_cp = constantPoolHandle(ik->constants()); |
2764 cp_cache = other_cp->cache(); | 2754 cp_cache = other_cp->cache(); |
2765 if (cp_cache != NULL) { | 2755 if (cp_cache != NULL) { |
2766 cp_cache->adjust_method_entries(_matching_old_methods, | 2756 cp_cache->adjust_method_entries(_matching_old_methods, |
2768 _matching_methods_length, | 2758 _matching_methods_length, |
2769 &trace_name_printed); | 2759 &trace_name_printed); |
2770 } | 2760 } |
2771 } | 2761 } |
2772 { | 2762 { |
2773 ResourceMark rm(THREAD); | 2763 ResourceMark rm(_thread); |
2774 // PreviousVersionInfo objects returned via PreviousVersionWalker | 2764 // PreviousVersionInfo objects returned via PreviousVersionWalker |
2775 // contain a GrowableArray of handles. We have to clean up the | 2765 // contain a GrowableArray of handles. We have to clean up the |
2776 // GrowableArray _after_ the PreviousVersionWalker destructor | 2766 // GrowableArray _after_ the PreviousVersionWalker destructor |
2777 // has destroyed the handles. | 2767 // has destroyed the handles. |
2778 { | 2768 { |
3206 // - replacing parts in the_class with parts from scratch_class | 3196 // - replacing parts in the_class with parts from scratch_class |
3207 // - adding a weak reference to track the obsolete but interesting | 3197 // - adding a weak reference to track the obsolete but interesting |
3208 // parts of the_class | 3198 // parts of the_class |
3209 // - adjusting constant pool caches and vtables in other classes | 3199 // - adjusting constant pool caches and vtables in other classes |
3210 // that refer to methods in the_class. These adjustments use the | 3200 // that refer to methods in the_class. These adjustments use the |
3211 // SystemDictionary::classes_do() facility which only allows | 3201 // ClassLoaderDataGraph::classes_do() facility which only allows |
3212 // a helper method to be specified. The interesting parameters | 3202 // a helper method to be specified. The interesting parameters |
3213 // that we would like to pass to the helper method are saved in | 3203 // that we would like to pass to the helper method are saved in |
3214 // static global fields in the VM operation. | 3204 // static global fields in the VM operation. |
3215 void VM_RedefineClasses::redefine_single_class(jclass the_jclass, | 3205 void VM_RedefineClasses::redefine_single_class(jclass the_jclass, |
3216 Klass* scratch_class_oop, TRAPS) { | 3206 Klass* scratch_class_oop, TRAPS) { |
3440 RC_TIMER_STOP(_timer_rsc_phase1); | 3430 RC_TIMER_STOP(_timer_rsc_phase1); |
3441 RC_TIMER_START(_timer_rsc_phase2); | 3431 RC_TIMER_START(_timer_rsc_phase2); |
3442 | 3432 |
3443 // Adjust constantpool caches and vtables for all classes | 3433 // Adjust constantpool caches and vtables for all classes |
3444 // that reference methods of the evolved class. | 3434 // that reference methods of the evolved class. |
3445 SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD); | 3435 AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD); |
3436 ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable); | |
3446 | 3437 |
3447 // JSR-292 support | 3438 // JSR-292 support |
3448 MemberNameTable* mnt = the_class->member_names(); | 3439 MemberNameTable* mnt = the_class->member_names(); |
3449 if (mnt != NULL) { | 3440 if (mnt != NULL) { |
3450 bool trace_name_printed = false; | 3441 bool trace_name_printed = false; |
3501 increment_class_counter(subik, THREAD); | 3492 increment_class_counter(subik, THREAD); |
3502 } | 3493 } |
3503 } | 3494 } |
3504 } | 3495 } |
3505 | 3496 |
3506 void VM_RedefineClasses::check_class(Klass* k_oop, | 3497 void VM_RedefineClasses::CheckClass::do_klass(Klass* k) { |
3507 ClassLoaderData* initiating_loader, | 3498 bool no_old_methods = true; // be optimistic |
3508 TRAPS) { | 3499 |
3509 Klass *k = k_oop; | 3500 // Both array and instance classes have vtables. |
3501 // a vtable should never contain old or obsolete methods | |
3502 ResourceMark rm(_thread); | |
3503 if (k->vtable_length() > 0 && | |
3504 !k->vtable()->check_no_old_or_obsolete_entries()) { | |
3505 if (RC_TRACE_ENABLED(0x00004000)) { | |
3506 RC_TRACE_WITH_THREAD(0x00004000, _thread, | |
3507 ("klassVtable::check_no_old_or_obsolete_entries failure" | |
3508 " -- OLD or OBSOLETE method found -- class: %s", | |
3509 k->signature_name())); | |
3510 k->vtable()->dump_vtable(); | |
3511 } | |
3512 no_old_methods = false; | |
3513 } | |
3514 | |
3510 if (k->oop_is_instance()) { | 3515 if (k->oop_is_instance()) { |
3511 HandleMark hm(THREAD); | 3516 HandleMark hm(_thread); |
3512 InstanceKlass *ik = (InstanceKlass *) k; | 3517 InstanceKlass *ik = InstanceKlass::cast(k); |
3513 bool no_old_methods = true; // be optimistic | |
3514 ResourceMark rm(THREAD); | |
3515 | |
3516 // a vtable should never contain old or obsolete methods | |
3517 if (ik->vtable_length() > 0 && | |
3518 !ik->vtable()->check_no_old_or_obsolete_entries()) { | |
3519 if (RC_TRACE_ENABLED(0x00004000)) { | |
3520 RC_TRACE_WITH_THREAD(0x00004000, THREAD, | |
3521 ("klassVtable::check_no_old_or_obsolete_entries failure" | |
3522 " -- OLD or OBSOLETE method found -- class: %s", | |
3523 ik->signature_name())); | |
3524 ik->vtable()->dump_vtable(); | |
3525 } | |
3526 no_old_methods = false; | |
3527 } | |
3528 | 3518 |
3529 // an itable should never contain old or obsolete methods | 3519 // an itable should never contain old or obsolete methods |
3530 if (ik->itable_length() > 0 && | 3520 if (ik->itable_length() > 0 && |
3531 !ik->itable()->check_no_old_or_obsolete_entries()) { | 3521 !ik->itable()->check_no_old_or_obsolete_entries()) { |
3532 if (RC_TRACE_ENABLED(0x00004000)) { | 3522 if (RC_TRACE_ENABLED(0x00004000)) { |
3533 RC_TRACE_WITH_THREAD(0x00004000, THREAD, | 3523 RC_TRACE_WITH_THREAD(0x00004000, _thread, |
3534 ("klassItable::check_no_old_or_obsolete_entries failure" | 3524 ("klassItable::check_no_old_or_obsolete_entries failure" |
3535 " -- OLD or OBSOLETE method found -- class: %s", | 3525 " -- OLD or OBSOLETE method found -- class: %s", |
3536 ik->signature_name())); | 3526 ik->signature_name())); |
3537 ik->itable()->dump_itable(); | 3527 ik->itable()->dump_itable(); |
3538 } | 3528 } |
3542 // the constant pool cache should never contain old or obsolete methods | 3532 // the constant pool cache should never contain old or obsolete methods |
3543 if (ik->constants() != NULL && | 3533 if (ik->constants() != NULL && |
3544 ik->constants()->cache() != NULL && | 3534 ik->constants()->cache() != NULL && |
3545 !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { | 3535 !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { |
3546 if (RC_TRACE_ENABLED(0x00004000)) { | 3536 if (RC_TRACE_ENABLED(0x00004000)) { |
3547 RC_TRACE_WITH_THREAD(0x00004000, THREAD, | 3537 RC_TRACE_WITH_THREAD(0x00004000, _thread, |
3548 ("cp-cache::check_no_old_or_obsolete_entries failure" | 3538 ("cp-cache::check_no_old_or_obsolete_entries failure" |
3549 " -- OLD or OBSOLETE method found -- class: %s", | 3539 " -- OLD or OBSOLETE method found -- class: %s", |
3550 ik->signature_name())); | 3540 ik->signature_name())); |
3551 ik->constants()->cache()->dump_cache(); | 3541 ik->constants()->cache()->dump_cache(); |
3552 } | 3542 } |
3553 no_old_methods = false; | 3543 no_old_methods = false; |
3554 } | 3544 } |
3555 | 3545 } |
3556 if (!no_old_methods) { | 3546 |
3557 if (RC_TRACE_ENABLED(0x00004000)) { | 3547 // print and fail guarantee if old methods are found. |
3558 dump_methods(); | 3548 if (!no_old_methods) { |
3559 } else { | 3549 if (RC_TRACE_ENABLED(0x00004000)) { |
3560 tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option " | 3550 dump_methods(); |
3561 "to see more info about the following guarantee() failure."); | 3551 } else { |
3562 } | 3552 tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option " |
3563 guarantee(false, "OLD and/or OBSOLETE method(s) found"); | 3553 "to see more info about the following guarantee() failure."); |
3564 } | 3554 } |
3555 guarantee(false, "OLD and/or OBSOLETE method(s) found"); | |
3565 } | 3556 } |
3566 } | 3557 } |
3558 | |
3567 | 3559 |
3568 void VM_RedefineClasses::dump_methods() { | 3560 void VM_RedefineClasses::dump_methods() { |
3569 int j; | 3561 int j; |
3570 RC_TRACE(0x00004000, ("_old_methods --")); | 3562 RC_TRACE(0x00004000, ("_old_methods --")); |
3571 for (j = 0; j < _old_methods->length(); ++j) { | 3563 for (j = 0; j < _old_methods->length(); ++j) { |