Ejemplo n.º 1
0
 FieldStreamBase(instanceKlassHandle klass) {
   _fields = klass->fields();
   _constants = klass->constants();
   _index = 0;
   _limit = klass->java_fields_count();
   init_generic_signature_start_slot();
 }
Ejemplo n.º 2
0
  // Field names and signatures are referenced via constantpool indexes. In the new class
  // version, the layout of the constantpool can be different, so these indexes should be
  // patched.
  void patch_indexes_for_fields(instanceKlassHandle k_h, instanceKlassHandle k_h_new) {
    typeArrayOop k_fields = k_h->fields();
    typeArrayOop k_new_fields = k_h_new->fields();
    int n_fields = k_fields->length();

    for (int i = 0; i < n_fields; i += instanceKlass::next_offset) {
      // name and signature
      k_fields->short_at_put(
        i + instanceKlass::name_index_offset,
        k_new_fields->short_at(i + instanceKlass::name_index_offset)
        );
      k_fields->short_at_put(
        i + instanceKlass::signature_index_offset,
        k_new_fields->short_at(i + instanceKlass::signature_index_offset)
        );
    }
  }
Ejemplo n.º 3
0
 AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {}
Ejemplo n.º 4
0
 InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {}
jvmtiError VM_RedefineClasses::compare_class_versions(instanceKlassHandle k_h_old, instanceKlassHandle k_h_new) {
  int i;

  // Check superclasses, or rather their names, since superclasses themselves can be
  // requested to replace. 
  // Check for NULL superclass first since this might be java.lang.Object
  if (k_h_old->super() != k_h_new->super() && 
      (k_h_old->super() == NULL || k_h_new->super() == NULL ||
       Klass::cast(k_h_old->super())->name() != Klass::cast(k_h_new->super())->name())) {
    return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
  }

  // Check if the number, names and order of directly implemented interfaces are the same.
  // I think in principle we should just check if the sets of names of directly implemented
  // interfaces are the same, i.e. the order of declaration (which, however, if changed in the
  // .java file, also changes in .class file) should not matter. However, comparing sets is
  // technically a bit more difficult, and, more importantly, I am not sure at present that the
  // order of interfaces does not matter on the implementation level, i.e. that the VM does not
  // rely on it somewhere.
  objArrayOop k_interfaces = k_h_old->local_interfaces();
  objArrayOop k_new_interfaces = k_h_new->local_interfaces();
  int n_intfs = k_interfaces->length();
  if (n_intfs != k_new_interfaces->length()) {
    return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
  }
  for (i = 0; i < n_intfs; i++) {
    if (Klass::cast((klassOop) k_interfaces->obj_at(i))->name() !=
        Klass::cast((klassOop) k_new_interfaces->obj_at(i))->name()) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
    }
  }

  // Check whether class is in the error init state.
  if (k_h_old->is_in_error_state()) {
    // TBD #5057930: special error code is needed in 1.6 
    return JVMTI_ERROR_INVALID_CLASS;
  }

  // Check whether class modifiers are the same.
  jushort old_flags = (jushort) k_h_old->access_flags().get_flags();
  jushort new_flags = (jushort) k_h_new->access_flags().get_flags();
  if (old_flags != new_flags) {
    return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
  }

  // Check if the number, names, types and order of fields declared in these classes
  // are the same.
  typeArrayOop k_old_fields = k_h_old->fields();
  typeArrayOop k_new_fields = k_h_new->fields();
  int n_fields = k_old_fields->length();
  if (n_fields != k_new_fields->length()) {
    return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
  }

  for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
    // access
    old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset);
    new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset);
    if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
    }
    // offset
    if (k_old_fields->short_at(i + instanceKlass::low_offset) != 
        k_new_fields->short_at(i + instanceKlass::low_offset) ||
        k_old_fields->short_at(i + instanceKlass::high_offset) != 
        k_new_fields->short_at(i + instanceKlass::high_offset)) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
    }
    // name and signature
    jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset);
    jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset);
    symbolOop name_sym1 = k_h_old->constants()->symbol_at(name_index);
    symbolOop sig_sym1 = k_h_old->constants()->symbol_at(sig_index);
    name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset);
    sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset);
    symbolOop name_sym2 = k_h_new->constants()->symbol_at(name_index);
    symbolOop sig_sym2 = k_h_new->constants()->symbol_at(sig_index);
    if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
    }
  }

  // Check if the number, names, signatures and order of methods declared in these classes
  // are the same.
  objArrayOop k_methods = k_h_old->methods();
  objArrayOop k_new_methods = k_h_new->methods();
  int n_methods = k_methods->length();
  if (n_methods < k_new_methods->length()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED;
  else if (n_methods > k_new_methods->length()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED;

  for (i = 0; i < n_methods; i++) {
    methodOop k_method = (methodOop) k_methods->obj_at(i);
    methodOop k_new_method = (methodOop) k_new_methods->obj_at(i);
    if (k_method->name() != k_new_method->name()) return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED;
    if (k_method->signature() != k_new_method->signature()) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED;
    }
    old_flags = (jushort) k_method->access_flags().get_flags();
    new_flags = (jushort) k_new_method->access_flags().get_flags();
    if (old_flags != new_flags) {
      return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED;
    }      
  }

  return JVMTI_ERROR_NONE;
}
Ejemplo n.º 6
0
  jvmdiError compare_class_versions(instanceKlassHandle k_h_old, instanceKlassHandle k_h_new) {
    int i;

    // Check whether essential class modifiers are the same. The rest can probably differ, e.g.
    // why not allow substitute class to be synthetic, if it satisfies other conditions.
    AccessFlags old_flags = k_h_old->access_flags();
    AccessFlags new_flags = k_h_new->access_flags();
    if (old_flags.is_public() != new_flags.is_public() ||
	old_flags.is_final() != new_flags.is_final() ||
	old_flags.is_interface() != new_flags.is_interface() ||
	old_flags.is_abstract() != new_flags.is_abstract()) {
      return JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED;
    }

    // Check superclasses, or rather their names, since superclasses themselves can be
    // requested to replace
    if (Klass::cast(k_h_old->super())->name() != Klass::cast(k_h_new->super())->name()) {
      return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED;
    }

    // Check if the number, names and order of directly implemented interfaces are the same.
    // I think in principle we should just check if the sets of names of directly implemented
    // interfaces are the same, i.e. the order of declaration (which, however, if changed in the
    // .java file, also changes in .class file) should not matter. However, comparing sets is
    // technically a bit more difficult, and, more importantly, I am not sure at present that the
    // order of interfaces does not matter on the implementation level, i.e. that the VM does not
    // rely on it somewhere.
    objArrayOop k_interfaces = k_h_old->local_interfaces();
    objArrayOop k_new_interfaces = k_h_new->local_interfaces();
    int n_intfs = k_interfaces->length();
    if (n_intfs != k_new_interfaces->length()) {
      return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED;
    }
    for (i = 0; i < n_intfs; i++) {
      if (Klass::cast((klassOop) k_interfaces->obj_at(i))->name() !=
	  Klass::cast((klassOop) k_new_interfaces->obj_at(i))->name()) {
        return JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED;
      }
    }

    // Check if the number, names, types and order of fields declared in these classes
    // are the same.
    typeArrayOop k_old_fields = k_h_old->fields();
    typeArrayOop k_new_fields = k_h_new->fields();
    int n_fields = k_old_fields->length();
    if (n_fields != k_new_fields->length()) {
      return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED;
    }

    for (i = 0; i < n_fields; i += instanceKlass::next_offset) {
      // access
      if (k_old_fields->ushort_at(i + instanceKlass::access_flags_offset) !=
        k_new_fields->ushort_at(i + instanceKlass::access_flags_offset)) {
        return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED;
      }
      // offset
      if (k_old_fields->short_at(i + instanceKlass::low_offset) != 
	  k_new_fields->short_at(i + instanceKlass::low_offset) ||
	  k_old_fields->short_at(i + instanceKlass::high_offset) != 
	  k_new_fields->short_at(i + instanceKlass::high_offset)) {
        return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED;
      }
      // name and signature
      jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset);
      jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset);
      symbolOop name_sym1 = k_h_old->constants()->symbol_at(name_index);
      symbolOop sig_sym1 = k_h_old->constants()->symbol_at(sig_index);
      name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset);
      sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset);
      symbolOop name_sym2 = k_h_new->constants()->symbol_at(name_index);
      symbolOop sig_sym2 = k_h_new->constants()->symbol_at(sig_index);
      if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
        return JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED;
      }
    }

    // Check if the number, names, signatures and order of methods declared in these classes
    // are the same.
    objArrayOop k_methods = k_h_old->methods();
    objArrayOop k_new_methods = k_h_new->methods();
    int n_methods = k_methods->length();
    if (n_methods < k_new_methods->length()) return JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED;
    else if (n_methods > k_new_methods->length()) return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED;

    for (i = 0; i < n_methods; i++) {
      methodOop k_method = (methodOop) k_methods->obj_at(i);
      methodOop k_new_method = (methodOop) k_new_methods->obj_at(i);
      if (k_method->name() != k_new_method->name()) return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED;
      if (k_method->signature() != k_new_method->signature()) {
        return JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED;
      }
      old_flags = k_method->access_flags();
      new_flags = k_new_method->access_flags();
      // It's probably safer to not compare the values of access_flags directly, since
      // some bits in them encode some implementation-specific information, e.g.
      // something about inlined tables. This may be different in the new version,
      // but should not affect method changeability.
      if (old_flags.is_public() != new_flags.is_public() ||
	  old_flags.is_protected() != new_flags.is_protected() ||
	  old_flags.is_private() != new_flags.is_private() ||
	  old_flags.is_static() != new_flags.is_static() ||
	  old_flags.is_final() != new_flags.is_final() ||
	  old_flags.is_synchronized() != new_flags.is_synchronized() ||
          old_flags.is_strict() != new_flags.is_strict() ||
	  old_flags.is_interface() != new_flags.is_interface() ||
	  old_flags.is_abstract() != new_flags.is_abstract()) {
        return JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED;
      }      
    }

    return JVMDI_ERROR_NONE;
  }