< prev index next >

src/hotspot/share/prims/jvmtiRedefineClasses.cpp

Print this page




 666   // Shrink the merge_cp operands
 667   merge_cp->shrink_operands(_operands_cur_length, CHECK);
 668 
 669   if (log_is_enabled(Trace, redefine, class, constantpool)) {
 670     // don't want to loop unless we are tracing
 671     int count = 0;
 672     for (int i = 1; i < _operands_index_map_p->length(); i++) {
 673       int value = _operands_index_map_p->at(i);
 674       if (value != -1) {
 675         log_trace(redefine, class, constantpool)("operands_index_map[%d]: old=%d new=%d", count, i, value);
 676         count++;
 677       }
 678     }
 679   }
 680   // Clean-up
 681   _operands_index_map_p = NULL;
 682   _operands_cur_length = 0;
 683   _operands_index_map_count = 0;
 684 } // end finalize_operands_merge()
 685 







 686 
 687 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
 688              InstanceKlass* the_class,
 689              InstanceKlass* scratch_class) {
 690   int i;
 691 
 692   // Check superclasses, or rather their names, since superclasses themselves can be
 693   // requested to replace.
 694   // Check for NULL superclass first since this might be java.lang.Object
 695   if (the_class->super() != scratch_class->super() &&
 696       (the_class->super() == NULL || scratch_class->super() == NULL ||
 697        the_class->super()->name() !=
 698        scratch_class->super()->name())) {
 699     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 700   }
 701 
 702   // Check if the number, names and order of directly implemented interfaces are the same.
 703   // I think in principle we should just check if the sets of names of directly implemented
 704   // interfaces are the same, i.e. the order of declaration (which, however, if changed in the
 705   // .java file, also changes in .class file) should not matter. However, comparing sets is


 708   // rely on it somewhere.
 709   Array<Klass*>* k_interfaces = the_class->local_interfaces();
 710   Array<Klass*>* k_new_interfaces = scratch_class->local_interfaces();
 711   int n_intfs = k_interfaces->length();
 712   if (n_intfs != k_new_interfaces->length()) {
 713     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 714   }
 715   for (i = 0; i < n_intfs; i++) {
 716     if (k_interfaces->at(i)->name() !=
 717         k_new_interfaces->at(i)->name()) {
 718       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 719     }
 720   }
 721 
 722   // Check whether class is in the error init state.
 723   if (the_class->is_in_error_state()) {
 724     // TBD #5057930: special error code is needed in 1.6
 725     return JVMTI_ERROR_INVALID_CLASS;
 726   }
 727 






























































































 728   // Check whether class modifiers are the same.
 729   jushort old_flags = (jushort) the_class->access_flags().get_flags();
 730   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
 731   if (old_flags != new_flags) {
 732     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
 733   }
 734 
 735   // Check if the number, names, types and order of fields declared in these classes
 736   // are the same.
 737   JavaFieldStream old_fs(the_class);
 738   JavaFieldStream new_fs(scratch_class);
 739   for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) {
 740     // access
 741     old_flags = old_fs.access_flags().as_short();
 742     new_flags = new_fs.access_flags().as_short();
 743     if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
 744       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
 745     }
 746     // offset
 747     if (old_fs.offset() != new_fs.offset()) {


1581 
1582     // Replace the new constant pool with a shrunken copy of the
1583     // merged constant pool so now the rewritten bytecodes have
1584     // valid references; the previous new constant pool will get
1585     // GCed.
1586     set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length,
1587                           CHECK_(JVMTI_ERROR_OUT_OF_MEMORY));
1588     // The new constant pool replaces scratch_cp so have cleaner clean it up.
1589     // It can't be cleaned up while there are handles to it.
1590     cp_cleaner.add_scratch_cp(scratch_cp());
1591   }
1592 
1593   return JVMTI_ERROR_NONE;
1594 } // end merge_cp_and_rewrite()
1595 
1596 
1597 // Rewrite constant pool references in klass scratch_class.
1598 bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
1599        TRAPS) {
1600 






1601   // rewrite constant pool references in the methods:
1602   if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
1603     // propagate failure back to caller
1604     return false;
1605   }
1606 
1607   // rewrite constant pool references in the class_annotations:
1608   if (!rewrite_cp_refs_in_class_annotations(scratch_class, THREAD)) {
1609     // propagate failure back to caller
1610     return false;
1611   }
1612 
1613   // rewrite constant pool references in the fields_annotations:
1614   if (!rewrite_cp_refs_in_fields_annotations(scratch_class, THREAD)) {
1615     // propagate failure back to caller
1616     return false;
1617   }
1618 
1619   // rewrite constant pool references in the methods_annotations:
1620   if (!rewrite_cp_refs_in_methods_annotations(scratch_class, THREAD)) {


1662   // rewrite source file name index:
1663   u2 source_file_name_idx = scratch_class->source_file_name_index();
1664   if (source_file_name_idx != 0) {
1665     u2 new_source_file_name_idx = find_new_index(source_file_name_idx);
1666     if (new_source_file_name_idx != 0) {
1667       scratch_class->set_source_file_name_index(new_source_file_name_idx);
1668     }
1669   }
1670 
1671   // rewrite class generic signature index:
1672   u2 generic_signature_index = scratch_class->generic_signature_index();
1673   if (generic_signature_index != 0) {
1674     u2 new_generic_signature_index = find_new_index(generic_signature_index);
1675     if (new_generic_signature_index != 0) {
1676       scratch_class->set_generic_signature_index(new_generic_signature_index);
1677     }
1678   }
1679 
1680   return true;
1681 } // end rewrite_cp_refs()
















1682 
1683 // Rewrite constant pool references in the methods.
1684 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
1685        InstanceKlass* scratch_class, TRAPS) {
1686 
1687   Array<Method*>* methods = scratch_class->methods();
1688 
1689   if (methods == NULL || methods->length() == 0) {
1690     // no methods so nothing to do
1691     return true;
1692   }
1693 
1694   // rewrite constant pool references in the methods:
1695   for (int i = methods->length() - 1; i >= 0; i--) {
1696     methodHandle method(THREAD, methods->at(i));
1697     methodHandle new_method;
1698     rewrite_cp_refs_in_method(method, &new_method, THREAD);
1699     if (!new_method.is_null()) {
1700       // the method has been replaced so save the new method version
1701       // even in the case of an exception.  original method is on the




 666   // Shrink the merge_cp operands
 667   merge_cp->shrink_operands(_operands_cur_length, CHECK);
 668 
 669   if (log_is_enabled(Trace, redefine, class, constantpool)) {
 670     // don't want to loop unless we are tracing
 671     int count = 0;
 672     for (int i = 1; i < _operands_index_map_p->length(); i++) {
 673       int value = _operands_index_map_p->at(i);
 674       if (value != -1) {
 675         log_trace(redefine, class, constantpool)("operands_index_map[%d]: old=%d new=%d", count, i, value);
 676         count++;
 677       }
 678     }
 679   }
 680   // Clean-up
 681   _operands_index_map_p = NULL;
 682   _operands_cur_length = 0;
 683   _operands_index_map_count = 0;
 684 } // end finalize_operands_merge()
 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 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
 695              InstanceKlass* the_class,
 696              InstanceKlass* scratch_class) {
 697   int i;
 698 
 699   // Check superclasses, or rather their names, since superclasses themselves can be
 700   // requested to replace.
 701   // Check for NULL superclass first since this might be java.lang.Object
 702   if (the_class->super() != scratch_class->super() &&
 703       (the_class->super() == NULL || scratch_class->super() == NULL ||
 704        the_class->super()->name() !=
 705        scratch_class->super()->name())) {
 706     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 707   }
 708 
 709   // Check if the number, names and order of directly implemented interfaces are the same.
 710   // I think in principle we should just check if the sets of names of directly implemented
 711   // interfaces are the same, i.e. the order of declaration (which, however, if changed in the
 712   // .java file, also changes in .class file) should not matter. However, comparing sets is


 715   // rely on it somewhere.
 716   Array<Klass*>* k_interfaces = the_class->local_interfaces();
 717   Array<Klass*>* k_new_interfaces = scratch_class->local_interfaces();
 718   int n_intfs = k_interfaces->length();
 719   if (n_intfs != k_new_interfaces->length()) {
 720     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 721   }
 722   for (i = 0; i < n_intfs; i++) {
 723     if (k_interfaces->at(i)->name() !=
 724         k_new_interfaces->at(i)->name()) {
 725       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 726     }
 727   }
 728 
 729   // Check whether class is in the error init state.
 730   if (the_class->is_in_error_state()) {
 731     // TBD #5057930: special error code is needed in 1.6
 732     return JVMTI_ERROR_INVALID_CLASS;
 733   }
 734 
 735   // Check whether the class NestHost attribute has been changed.
 736   {
 737     Thread* thread = Thread::current();
 738     ResourceMark rm(thread);
 739     JvmtiThreadState *state = JvmtiThreadState::state_for((JavaThread*)thread);
 740     RedefineVerifyMark rvm(the_class, scratch_class, state);
 741     u2 the_nest_host_idx = the_class->nest_host_index();
 742     u2 scr_nest_host_idx = scratch_class->nest_host_index();
 743 
 744     if (the_nest_host_idx != 0 && scr_nest_host_idx != 0) {
 745       Symbol* the_sym = the_class->constants()->klass_name_at(the_nest_host_idx);
 746       Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_nest_host_idx);
 747       if (the_sym != scr_sym) {
 748         log_trace(redefine, class, nestmates)
 749           ("redefined class %s attribute change error: NestHost class: %s replaced with: %s",
 750            the_class->external_name(), the_sym->as_C_string(), scr_sym->as_C_string());
 751         return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 752       }
 753     } else if ((the_nest_host_idx == 0) ^ (scr_nest_host_idx == 0)) {
 754       const char* action_str = (the_nest_host_idx != 0) ? "removed" : "added";
 755       log_trace(redefine, class, nestmates)
 756         ("redefined class %s attribute change error: NestHost attribute %s",
 757          the_class->external_name(), action_str);
 758       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 759     }
 760 
 761     // Check whether the class NestMembers attribute has been changed.
 762     Array<u2>* the_nest_members = the_class->nest_members();
 763     Array<u2>* scr_nest_members = scratch_class->nest_members();
 764     bool the_members_exists = the_nest_members != Universe::the_empty_short_array();
 765     bool scr_members_exists = scr_nest_members != Universe::the_empty_short_array();
 766 
 767     int members_len = the_nest_members->length();
 768     if (the_members_exists && scr_members_exists) {
 769       if (members_len != scr_nest_members->length()) {
 770         log_trace(redefine, class, nestmates)
 771           ("redefined class %s attribute change error: NestMember len=%d changed to len=%d",
 772            the_class->external_name(), members_len, scr_nest_members->length());
 773         return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 774       }
 775 
 776       // The order of entries in the NestMembers array is not specified so we
 777       // have to explicitly check for the same contents. We do this by copying
 778       // the referenced symbols into their own arrays, sorting them and then
 779       // comparing each element pair.
 780 
 781       Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
 782       Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
 783 
 784       if (the_syms == NULL || scr_syms == NULL) {
 785         return JVMTI_ERROR_OUT_OF_MEMORY;
 786       }
 787 
 788       for (int i = 0; i < members_len; i++) {
 789         int the_cp_index = the_nest_members->at(i);
 790         int scr_cp_index = scr_nest_members->at(i);
 791         the_syms[i] = the_class->constants()->klass_name_at(the_cp_index);
 792         scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index);
 793       }
 794 
 795       qsort(the_syms, members_len, sizeof(Symbol*), symcmp);
 796       qsort(scr_syms, members_len, sizeof(Symbol*), symcmp);
 797 
 798       for (int i = 0; i < members_len; i++) {
 799         if (the_syms[i] != scr_syms[i]) {
 800           log_trace(redefine, class, nestmates)
 801             ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s",
 802              the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string());
 803           return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 804         }
 805       }
 806       /*
 807       for (int i = 0; i < members_len; i++) {
 808         int the_cp_index = the_nest_members->at(i);
 809         int scr_cp_index = scr_nest_members->at(i);
 810         Symbol* the_sym = the_class->constants()->klass_name_at(the_cp_index);
 811         Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_cp_index);
 812         if (the_sym != scr_sym) {
 813           log_trace(redefine, class, nestmates)
 814             ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s",
 815              the_class->external_name(), i, the_sym->as_C_string(), scr_sym->as_C_string());
 816           return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 817         }
 818       }
 819       */
 820     } else if (the_members_exists ^ scr_members_exists) {
 821       const char* action_str = (the_members_exists) ? "removed" : "added";
 822       log_trace(redefine, class, nestmates)
 823         ("redefined class %s attribute change error: NestMembers attribute %s",
 824          the_class->external_name(), action_str);
 825       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
 826     }
 827   }
 828 
 829   // Check whether class modifiers are the same.
 830   jushort old_flags = (jushort) the_class->access_flags().get_flags();
 831   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
 832   if (old_flags != new_flags) {
 833     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
 834   }
 835 
 836   // Check if the number, names, types and order of fields declared in these classes
 837   // are the same.
 838   JavaFieldStream old_fs(the_class);
 839   JavaFieldStream new_fs(scratch_class);
 840   for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) {
 841     // access
 842     old_flags = old_fs.access_flags().as_short();
 843     new_flags = new_fs.access_flags().as_short();
 844     if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
 845       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
 846     }
 847     // offset
 848     if (old_fs.offset() != new_fs.offset()) {


1682 
1683     // Replace the new constant pool with a shrunken copy of the
1684     // merged constant pool so now the rewritten bytecodes have
1685     // valid references; the previous new constant pool will get
1686     // GCed.
1687     set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length,
1688                           CHECK_(JVMTI_ERROR_OUT_OF_MEMORY));
1689     // The new constant pool replaces scratch_cp so have cleaner clean it up.
1690     // It can't be cleaned up while there are handles to it.
1691     cp_cleaner.add_scratch_cp(scratch_cp());
1692   }
1693 
1694   return JVMTI_ERROR_NONE;
1695 } // end merge_cp_and_rewrite()
1696 
1697 
1698 // Rewrite constant pool references in klass scratch_class.
1699 bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
1700        TRAPS) {
1701 
1702   // rewrite constant pool references in the nest attributes:
1703   if (!rewrite_cp_refs_in_nest_attributes(scratch_class)) {
1704     // propagate failure back to caller
1705     return false;
1706   }
1707 
1708   // rewrite constant pool references in the methods:
1709   if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
1710     // propagate failure back to caller
1711     return false;
1712   }
1713 
1714   // rewrite constant pool references in the class_annotations:
1715   if (!rewrite_cp_refs_in_class_annotations(scratch_class, THREAD)) {
1716     // propagate failure back to caller
1717     return false;
1718   }
1719 
1720   // rewrite constant pool references in the fields_annotations:
1721   if (!rewrite_cp_refs_in_fields_annotations(scratch_class, THREAD)) {
1722     // propagate failure back to caller
1723     return false;
1724   }
1725 
1726   // rewrite constant pool references in the methods_annotations:
1727   if (!rewrite_cp_refs_in_methods_annotations(scratch_class, THREAD)) {


1769   // rewrite source file name index:
1770   u2 source_file_name_idx = scratch_class->source_file_name_index();
1771   if (source_file_name_idx != 0) {
1772     u2 new_source_file_name_idx = find_new_index(source_file_name_idx);
1773     if (new_source_file_name_idx != 0) {
1774       scratch_class->set_source_file_name_index(new_source_file_name_idx);
1775     }
1776   }
1777 
1778   // rewrite class generic signature index:
1779   u2 generic_signature_index = scratch_class->generic_signature_index();
1780   if (generic_signature_index != 0) {
1781     u2 new_generic_signature_index = find_new_index(generic_signature_index);
1782     if (new_generic_signature_index != 0) {
1783       scratch_class->set_generic_signature_index(new_generic_signature_index);
1784     }
1785   }
1786 
1787   return true;
1788 } // end rewrite_cp_refs()
1789 
1790 // Rewrite constant pool references in the NestHost and NestMembers attributes.
1791 bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes(
1792        InstanceKlass* scratch_class) {
1793 
1794   u2 cp_index = scratch_class->nest_host_index();
1795   if (cp_index != 0) {
1796     scratch_class->set_nest_host_index(find_new_index(cp_index));
1797   }
1798   Array<u2>* nest_members = scratch_class->nest_members();
1799   for (int i = 0; i < nest_members->length(); i++) {
1800     u2 cp_index = nest_members->at(i);
1801     nest_members->at_put(i, find_new_index(cp_index));
1802   }
1803   return true;
1804 }
1805 
1806 // Rewrite constant pool references in the methods.
1807 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
1808        InstanceKlass* scratch_class, TRAPS) {
1809 
1810   Array<Method*>* methods = scratch_class->methods();
1811 
1812   if (methods == NULL || methods->length() == 0) {
1813     // no methods so nothing to do
1814     return true;
1815   }
1816 
1817   // rewrite constant pool references in the methods:
1818   for (int i = methods->length() - 1; i >= 0; i--) {
1819     methodHandle method(THREAD, methods->at(i));
1820     methodHandle new_method;
1821     rewrite_cp_refs_in_method(method, &new_method, THREAD);
1822     if (!new_method.is_null()) {
1823       // the method has been replaced so save the new method version
1824       // even in the case of an exception.  original method is on the


< prev index next >