< prev index next >

src/hotspot/share/prims/jvmtiRedefineClasses.cpp

Print this page
rev 50604 : imported patch jep181-rev1
rev 50605 : imported patch jep181-rev2


 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 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 }
 775 
 776 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
 777              InstanceKlass* the_class,
 778              InstanceKlass* scratch_class) {
 779   int i;
 780 
 781   // Check superclasses, or rather their names, since superclasses themselves can be
 782   // requested to replace.
 783   // Check for NULL superclass first since this might be java.lang.Object
 784   if (the_class->super() != scratch_class->super() &&
 785       (the_class->super() == NULL || scratch_class->super() == NULL ||
 786        the_class->super()->name() !=
 787        scratch_class->super()->name())) {
 788     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 789   }
 790 
 791   // Check if the number, names and order of directly implemented interfaces are the same.
 792   // I think in principle we should just check if the sets of names of directly implemented
 793   // interfaces are the same, i.e. the order of declaration (which, however, if changed in the
 794   // .java file, also changes in .class file) should not matter. However, comparing sets is


 797   // rely on it somewhere.
 798   Array<Klass*>* k_interfaces = the_class->local_interfaces();
 799   Array<Klass*>* k_new_interfaces = scratch_class->local_interfaces();
 800   int n_intfs = k_interfaces->length();
 801   if (n_intfs != k_new_interfaces->length()) {
 802     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 803   }
 804   for (i = 0; i < n_intfs; i++) {
 805     if (k_interfaces->at(i)->name() !=
 806         k_new_interfaces->at(i)->name()) {
 807       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
 808     }
 809   }
 810 
 811   // Check whether class is in the error init state.
 812   if (the_class->is_in_error_state()) {
 813     // TBD #5057930: special error code is needed in 1.6
 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;
 821   }
 822 
 823   // Check whether class modifiers are the same.
 824   jushort old_flags = (jushort) the_class->access_flags().get_flags();
 825   jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
 826   if (old_flags != new_flags) {
 827     return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
 828   }
 829 
 830   // Check if the number, names, types and order of fields declared in these classes
 831   // are the same.
 832   JavaFieldStream old_fs(the_class);
 833   JavaFieldStream new_fs(scratch_class);
 834   for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) {
 835     // access
 836     old_flags = old_fs.access_flags().as_short();
 837     new_flags = new_fs.access_flags().as_short();
 838     if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
 839       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
 840     }
 841     // offset
 842     if (old_fs.offset() != new_fs.offset()) {


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


1763   // rewrite source file name index:
1764   u2 source_file_name_idx = scratch_class->source_file_name_index();
1765   if (source_file_name_idx != 0) {
1766     u2 new_source_file_name_idx = find_new_index(source_file_name_idx);
1767     if (new_source_file_name_idx != 0) {
1768       scratch_class->set_source_file_name_index(new_source_file_name_idx);
1769     }
1770   }
1771 
1772   // rewrite class generic signature index:
1773   u2 generic_signature_index = scratch_class->generic_signature_index();
1774   if (generic_signature_index != 0) {
1775     u2 new_generic_signature_index = find_new_index(generic_signature_index);
1776     if (new_generic_signature_index != 0) {
1777       scratch_class->set_generic_signature_index(new_generic_signature_index);
1778     }
1779   }
1780 
1781   return true;
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 }
1799 
1800 // Rewrite constant pool references in the methods.
1801 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
1802        InstanceKlass* scratch_class, TRAPS) {
1803 
1804   Array<Method*>* methods = scratch_class->methods();
1805 
1806   if (methods == NULL || methods->length() == 0) {
1807     // no methods so nothing to do
1808     return true;
1809   }
1810 
1811   // rewrite constant pool references in the methods:
1812   for (int i = methods->length() - 1; i >= 0; i--) {
1813     methodHandle method(THREAD, methods->at(i));
1814     methodHandle new_method;
1815     rewrite_cp_refs_in_method(method, &new_method, THREAD);
1816     if (!new_method.is_null()) {
1817       // the method has been replaced so save the new method version
1818       // even in the case of an exception.  original method is on the


< prev index next >