comparison src/share/vm/oops/instanceKlass.cpp @ 12281:4f9a42c33738

8022887: Assertion hit while using class and redefining it with RedefineClasses simultaneously Summary: Need to refetch each method from InstanceKlass after all safepoints. Removed leaky PreviousVersionInfo code. Reviewed-by: dcubed, sspitsyn
author coleenp
date Fri, 20 Sep 2013 09:30:02 -0400
parents e22ee8e7ae62
children 0f37d1badced
comparison
equal deleted inserted replaced
12279:6eb908998b32 12281:4f9a42c33738
2845 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); 2845 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr();
2846 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); 2846 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr();
2847 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); 2847 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr();
2848 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); 2848 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
2849 { 2849 {
2850 ResourceMark rm; 2850 bool have_pv = false;
2851 // PreviousVersionInfo objects returned via PreviousVersionWalker 2851 PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
2852 // contain a GrowableArray of handles. We have to clean up the 2852 for (PreviousVersionNode * pv_node = pvw.next_previous_version();
2853 // GrowableArray _after_ the PreviousVersionWalker destructor 2853 pv_node != NULL; pv_node = pvw.next_previous_version()) {
2854 // has destroyed the handles. 2854 if (!have_pv)
2855 { 2855 st->print(BULLET"previous version: ");
2856 bool have_pv = false; 2856 have_pv = true;
2857 PreviousVersionWalker pvw((InstanceKlass*)this); 2857 pv_node->prev_constant_pool()->print_value_on(st);
2858 for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); 2858 }
2859 pv_info != NULL; pv_info = pvw.next_previous_version()) { 2859 if (have_pv) st->cr();
2860 if (!have_pv) 2860 } // pvw is cleaned up
2861 st->print(BULLET"previous version: ");
2862 have_pv = true;
2863 pv_info->prev_constant_pool_handle()()->print_value_on(st);
2864 }
2865 if (have_pv) st->cr();
2866 } // pvw is cleaned up
2867 } // rm is cleaned up
2868 2861
2869 if (generic_signature() != NULL) { 2862 if (generic_signature() != NULL) {
2870 st->print(BULLET"generic signature: "); 2863 st->print(BULLET"generic signature: ");
2871 generic_signature()->print_value_on(st); 2864 generic_signature()->print_value_on(st);
2872 st->cr(); 2865 st->cr();
3390 // we don't need to create a new PreviousVersionNode. However, 3383 // we don't need to create a new PreviousVersionNode. However,
3391 // we still need to examine older previous versions below. 3384 // we still need to examine older previous versions below.
3392 Array<Method*>* old_methods = ikh->methods(); 3385 Array<Method*>* old_methods = ikh->methods();
3393 3386
3394 if (cp_ref->on_stack()) { 3387 if (cp_ref->on_stack()) {
3395 PreviousVersionNode * pv_node = NULL; 3388 PreviousVersionNode * pv_node = NULL;
3396 if (emcp_method_count == 0) { 3389 if (emcp_method_count == 0) {
3397 // non-shared ConstantPool gets a reference 3390 // non-shared ConstantPool gets a reference
3398 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), NULL); 3391 pv_node = new PreviousVersionNode(cp_ref, NULL);
3399 RC_TRACE(0x00000400, 3392 RC_TRACE(0x00000400,
3400 ("add: all methods are obsolete; flushing any EMCP refs")); 3393 ("add: all methods are obsolete; flushing any EMCP refs"));
3401 } else { 3394 } else {
3402 int local_count = 0; 3395 int local_count = 0;
3403 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) 3396 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
3404 GrowableArray<Method*>(emcp_method_count, true); 3397 GrowableArray<Method*>(emcp_method_count, true);
3405 for (int i = 0; i < old_methods->length(); i++) { 3398 for (int i = 0; i < old_methods->length(); i++) {
3406 if (emcp_methods->at(i)) { 3399 if (emcp_methods->at(i)) {
3407 // this old method is EMCP. Save it only if it's on the stack 3400 // this old method is EMCP. Save it only if it's on the stack
3408 Method* old_method = old_methods->at(i); 3401 Method* old_method = old_methods->at(i);
3409 if (old_method->on_stack()) { 3402 if (old_method->on_stack()) {
3410 method_refs->append(old_method); 3403 method_refs->append(old_method);
3404 }
3405 if (++local_count >= emcp_method_count) {
3406 // no more EMCP methods so bail out now
3407 break;
3411 } 3408 }
3412 if (++local_count >= emcp_method_count) {
3413 // no more EMCP methods so bail out now
3414 break;
3415 } 3409 }
3416 } 3410 }
3417 }
3418 // non-shared ConstantPool gets a reference 3411 // non-shared ConstantPool gets a reference
3419 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), method_refs); 3412 pv_node = new PreviousVersionNode(cp_ref, method_refs);
3420 } 3413 }
3421 // append new previous version. 3414 // append new previous version.
3422 _previous_versions->append(pv_node); 3415 _previous_versions->append(pv_node);
3423 } 3416 }
3424 3417
3425 // Since the caller is the VMThread and we are at a safepoint, this 3418 // Since the caller is the VMThread and we are at a safepoint, this
3426 // is a good time to clear out unused references. 3419 // is a good time to clear out unused references.
3427 3420
3518 m = methods()->at(index); 3511 m = methods()->at(index);
3519 if (m->method_idnum() == idnum) { 3512 if (m->method_idnum() == idnum) {
3520 return m; 3513 return m;
3521 } 3514 }
3522 } 3515 }
3516 // None found, return null for the caller to handle.
3517 return NULL;
3523 } 3518 }
3524 return m; 3519 return m;
3525 } 3520 }
3526 3521
3527 jint InstanceKlass::get_cached_class_file_len() { 3522 jint InstanceKlass::get_cached_class_file_len() {
3534 3529
3535 3530
3536 // Construct a PreviousVersionNode entry for the array hung off 3531 // Construct a PreviousVersionNode entry for the array hung off
3537 // the InstanceKlass. 3532 // the InstanceKlass.
3538 PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, 3533 PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
3539 bool prev_cp_is_weak, GrowableArray<Method*>* prev_EMCP_methods) { 3534 GrowableArray<Method*>* prev_EMCP_methods) {
3540 3535
3541 _prev_constant_pool = prev_constant_pool; 3536 _prev_constant_pool = prev_constant_pool;
3542 _prev_cp_is_weak = prev_cp_is_weak;
3543 _prev_EMCP_methods = prev_EMCP_methods; 3537 _prev_EMCP_methods = prev_EMCP_methods;
3544 } 3538 }
3545 3539
3546 3540
3547 // Destroy a PreviousVersionNode 3541 // Destroy a PreviousVersionNode
3553 if (_prev_EMCP_methods != NULL) { 3547 if (_prev_EMCP_methods != NULL) {
3554 delete _prev_EMCP_methods; 3548 delete _prev_EMCP_methods;
3555 } 3549 }
3556 } 3550 }
3557 3551
3558
3559 // Construct a PreviousVersionInfo entry
3560 PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) {
3561 _prev_constant_pool_handle = constantPoolHandle(); // NULL handle
3562 _prev_EMCP_method_handles = NULL;
3563
3564 ConstantPool* cp = pv_node->prev_constant_pool();
3565 assert(cp != NULL, "constant pool ref was unexpectedly cleared");
3566 if (cp == NULL) {
3567 return; // robustness
3568 }
3569
3570 // make the ConstantPool* safe to return
3571 _prev_constant_pool_handle = constantPoolHandle(cp);
3572
3573 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
3574 if (method_refs == NULL) {
3575 // the InstanceKlass did not have any EMCP methods
3576 return;
3577 }
3578
3579 _prev_EMCP_method_handles = new GrowableArray<methodHandle>(10);
3580
3581 int n_methods = method_refs->length();
3582 for (int i = 0; i < n_methods; i++) {
3583 Method* method = method_refs->at(i);
3584 assert (method != NULL, "method has been cleared");
3585 if (method == NULL) {
3586 continue; // robustness
3587 }
3588 // make the Method* safe to return
3589 _prev_EMCP_method_handles->append(methodHandle(method));
3590 }
3591 }
3592
3593
3594 // Destroy a PreviousVersionInfo
3595 PreviousVersionInfo::~PreviousVersionInfo() {
3596 // Since _prev_EMCP_method_handles is not C-heap allocated, we
3597 // don't have to delete it.
3598 }
3599
3600
3601 // Construct a helper for walking the previous versions array 3552 // Construct a helper for walking the previous versions array
3602 PreviousVersionWalker::PreviousVersionWalker(InstanceKlass *ik) { 3553 PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
3554 _thread = thread;
3603 _previous_versions = ik->previous_versions(); 3555 _previous_versions = ik->previous_versions();
3604 _current_index = 0; 3556 _current_index = 0;
3605 // _hm needs no initialization
3606 _current_p = NULL; 3557 _current_p = NULL;
3607 } 3558 _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
3608
3609
3610 // Destroy a PreviousVersionWalker
3611 PreviousVersionWalker::~PreviousVersionWalker() {
3612 // Delete the current info just in case the caller didn't walk to
3613 // the end of the previous versions list. No harm if _current_p is
3614 // already NULL.
3615 delete _current_p;
3616
3617 // When _hm is destroyed, all the Handles returned in
3618 // PreviousVersionInfo objects will be destroyed.
3619 // Also, after this destructor is finished it will be
3620 // safe to delete the GrowableArray allocated in the
3621 // PreviousVersionInfo objects.
3622 } 3559 }
3623 3560
3624 3561
3625 // Return the interesting information for the next previous version 3562 // Return the interesting information for the next previous version
3626 // of the klass. Returns NULL if there are no more previous versions. 3563 // of the klass. Returns NULL if there are no more previous versions.
3627 PreviousVersionInfo* PreviousVersionWalker::next_previous_version() { 3564 PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
3628 if (_previous_versions == NULL) { 3565 if (_previous_versions == NULL) {
3629 // no previous versions so nothing to return 3566 // no previous versions so nothing to return
3630 return NULL; 3567 return NULL;
3631 } 3568 }
3632 3569
3633 delete _current_p; // cleanup the previous info for the caller 3570 _current_p = NULL; // reset to NULL
3634 _current_p = NULL; // reset to NULL so we don't delete same object twice 3571 _current_constant_pool_handle = NULL;
3635 3572
3636 int length = _previous_versions->length(); 3573 int length = _previous_versions->length();
3637 3574
3638 while (_current_index < length) { 3575 while (_current_index < length) {
3639 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); 3576 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
3640 PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass) 3577
3641 PreviousVersionInfo(pv_node); 3578 // Save a handle to the constant pool for this previous version,
3642 3579 // which keeps all the methods from being deallocated.
3643 constantPoolHandle cp_h = pv_info->prev_constant_pool_handle(); 3580 _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
3644 assert (!cp_h.is_null(), "null cp found in previous version"); 3581 _current_p = pv_node;
3645 3582 return pv_node;
3646 // The caller will need to delete pv_info when they are done with it. 3583 }
3647 _current_p = pv_info; 3584
3648 return pv_info;
3649 }
3650
3651 // all of the underlying nodes' info has been deleted
3652 return NULL; 3585 return NULL;
3653 } // end next_previous_version() 3586 } // end next_previous_version()