681 _operands_index_map_p = NULL; |
681 _operands_index_map_p = NULL; |
682 _operands_cur_length = 0; |
682 _operands_cur_length = 0; |
683 _operands_index_map_count = 0; |
683 _operands_index_map_count = 0; |
684 } // end finalize_operands_merge() |
684 } // end finalize_operands_merge() |
685 |
685 |
|
686 // Symbol* comparator for qsort |
|
687 // The caller must have an active ResourceMark. |
|
688 static int symcmp(const void* a, const void* b) { |
|
689 char* astr = (*(Symbol**)a)->as_C_string(); |
|
690 char* bstr = (*(Symbol**)b)->as_C_string(); |
|
691 return strcmp(astr, bstr); |
|
692 } |
|
693 |
|
694 static jvmtiError check_nest_attributes(InstanceKlass* the_class, |
|
695 InstanceKlass* scratch_class) { |
|
696 // Check whether the class NestHost attribute has been changed. |
|
697 Thread* thread = Thread::current(); |
|
698 ResourceMark rm(thread); |
|
699 JvmtiThreadState *state = JvmtiThreadState::state_for((JavaThread*)thread); |
|
700 u2 the_nest_host_idx = the_class->nest_host_index(); |
|
701 u2 scr_nest_host_idx = scratch_class->nest_host_index(); |
|
702 |
|
703 if (the_nest_host_idx != 0 && scr_nest_host_idx != 0) { |
|
704 Symbol* the_sym = the_class->constants()->klass_name_at(the_nest_host_idx); |
|
705 Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_nest_host_idx); |
|
706 if (the_sym != scr_sym) { |
|
707 log_trace(redefine, class, nestmates) |
|
708 ("redefined class %s attribute change error: NestHost class: %s replaced with: %s", |
|
709 the_class->external_name(), the_sym->as_C_string(), scr_sym->as_C_string()); |
|
710 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; |
|
711 } |
|
712 } else if ((the_nest_host_idx == 0) ^ (scr_nest_host_idx == 0)) { |
|
713 const char* action_str = (the_nest_host_idx != 0) ? "removed" : "added"; |
|
714 log_trace(redefine, class, nestmates) |
|
715 ("redefined class %s attribute change error: NestHost attribute %s", |
|
716 the_class->external_name(), action_str); |
|
717 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; |
|
718 } |
|
719 |
|
720 // Check whether the class NestMembers attribute has been changed. |
|
721 Array<u2>* the_nest_members = the_class->nest_members(); |
|
722 Array<u2>* scr_nest_members = scratch_class->nest_members(); |
|
723 bool the_members_exists = the_nest_members != Universe::the_empty_short_array(); |
|
724 bool scr_members_exists = scr_nest_members != Universe::the_empty_short_array(); |
|
725 |
|
726 int members_len = the_nest_members->length(); |
|
727 if (the_members_exists && scr_members_exists) { |
|
728 if (members_len != scr_nest_members->length()) { |
|
729 log_trace(redefine, class, nestmates) |
|
730 ("redefined class %s attribute change error: NestMember len=%d changed to len=%d", |
|
731 the_class->external_name(), members_len, scr_nest_members->length()); |
|
732 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; |
|
733 } |
|
734 |
|
735 // The order of entries in the NestMembers array is not specified so we |
|
736 // have to explicitly check for the same contents. We do this by copying |
|
737 // the referenced symbols into their own arrays, sorting them and then |
|
738 // comparing each element pair. |
|
739 |
|
740 Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len); |
|
741 Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len); |
|
742 |
|
743 if (the_syms == NULL || scr_syms == NULL) { |
|
744 return JVMTI_ERROR_OUT_OF_MEMORY; |
|
745 } |
|
746 |
|
747 for (int i = 0; i < members_len; i++) { |
|
748 int the_cp_index = the_nest_members->at(i); |
|
749 int scr_cp_index = scr_nest_members->at(i); |
|
750 the_syms[i] = the_class->constants()->klass_name_at(the_cp_index); |
|
751 scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index); |
|
752 } |
|
753 |
|
754 qsort(the_syms, members_len, sizeof(Symbol*), symcmp); |
|
755 qsort(scr_syms, members_len, sizeof(Symbol*), symcmp); |
|
756 |
|
757 for (int i = 0; i < members_len; i++) { |
|
758 if (the_syms[i] != scr_syms[i]) { |
|
759 log_trace(redefine, class, nestmates) |
|
760 ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s", |
|
761 the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string()); |
|
762 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; |
|
763 } |
|
764 } |
|
765 } else if (the_members_exists ^ scr_members_exists) { |
|
766 const char* action_str = (the_members_exists) ? "removed" : "added"; |
|
767 log_trace(redefine, class, nestmates) |
|
768 ("redefined class %s attribute change error: NestMembers attribute %s", |
|
769 the_class->external_name(), action_str); |
|
770 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; |
|
771 } |
|
772 |
|
773 return JVMTI_ERROR_NONE; |
|
774 } |
686 |
775 |
687 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( |
776 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( |
688 InstanceKlass* the_class, |
777 InstanceKlass* the_class, |
689 InstanceKlass* scratch_class) { |
778 InstanceKlass* scratch_class) { |
690 int i; |
779 int i; |