src/hotspot/share/prims/jvmtiRedefineClasses.cpp
changeset 50735 2f2af62dfac7
parent 49594 898ef81cbc0e
child 51096 695dff91a997
equal deleted inserted replaced
50734:0828a0f6676b 50735:2f2af62dfac7
   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;
   721 
   810 
   722   // Check whether class is in the error init state.
   811   // Check whether class is in the error init state.
   723   if (the_class->is_in_error_state()) {
   812   if (the_class->is_in_error_state()) {
   724     // TBD #5057930: special error code is needed in 1.6
   813     // TBD #5057930: special error code is needed in 1.6
   725     return JVMTI_ERROR_INVALID_CLASS;
   814     return JVMTI_ERROR_INVALID_CLASS;
       
   815   }
       
   816 
       
   817   // Check whether the nest-related attributes have been changed.
       
   818   jvmtiError err = check_nest_attributes(the_class, scratch_class);
       
   819   if (err != JVMTI_ERROR_NONE) {
       
   820     return err;
   726   }
   821   }
   727 
   822 
   728   // Check whether class modifiers are the same.
   823   // Check whether class modifiers are the same.
   729   jushort old_flags = (jushort) the_class->access_flags().get_flags();
   824   jushort old_flags = (jushort) the_class->access_flags().get_flags();
   730   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
   825   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
  1596 
  1691 
  1597 // Rewrite constant pool references in klass scratch_class.
  1692 // Rewrite constant pool references in klass scratch_class.
  1598 bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
  1693 bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
  1599        TRAPS) {
  1694        TRAPS) {
  1600 
  1695 
       
  1696   // rewrite constant pool references in the nest attributes:
       
  1697   if (!rewrite_cp_refs_in_nest_attributes(scratch_class)) {
       
  1698     // propagate failure back to caller
       
  1699     return false;
       
  1700   }
       
  1701 
  1601   // rewrite constant pool references in the methods:
  1702   // rewrite constant pool references in the methods:
  1602   if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
  1703   if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
  1603     // propagate failure back to caller
  1704     // propagate failure back to caller
  1604     return false;
  1705     return false;
  1605   }
  1706   }
  1677     }
  1778     }
  1678   }
  1779   }
  1679 
  1780 
  1680   return true;
  1781   return true;
  1681 } // end rewrite_cp_refs()
  1782 } // end rewrite_cp_refs()
       
  1783 
       
  1784 // Rewrite constant pool references in the NestHost and NestMembers attributes.
       
  1785 bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes(
       
  1786        InstanceKlass* scratch_class) {
       
  1787 
       
  1788   u2 cp_index = scratch_class->nest_host_index();
       
  1789   if (cp_index != 0) {
       
  1790     scratch_class->set_nest_host_index(find_new_index(cp_index));
       
  1791   }
       
  1792   Array<u2>* nest_members = scratch_class->nest_members();
       
  1793   for (int i = 0; i < nest_members->length(); i++) {
       
  1794     u2 cp_index = nest_members->at(i);
       
  1795     nest_members->at_put(i, find_new_index(cp_index));
       
  1796   }
       
  1797   return true;
       
  1798 }
  1682 
  1799 
  1683 // Rewrite constant pool references in the methods.
  1800 // Rewrite constant pool references in the methods.
  1684 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
  1801 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
  1685        InstanceKlass* scratch_class, TRAPS) {
  1802        InstanceKlass* scratch_class, TRAPS) {
  1686 
  1803