jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
  // For consistency allocate memory using os::malloc wrapper.
  _k_h_new = (instanceKlassHandle *) os::malloc(sizeof(instanceKlassHandle) * _class_count);

  ResourceMark rm(THREAD);

  JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state();
  assert(state != NULL, "JvmtiThreadState not initialized"); 
  for (int i = 0; i < _class_count; i++) {
    oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
    klassOop k_oop = java_lang_Class::as_klassOop(mirror);
    instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop);
    symbolHandle k_name = symbolHandle(THREAD, k_h->name());

    ClassFileStream st((u1*) _class_defs[i].class_bytes,
      _class_defs[i].class_byte_count, (char *)"__VM_RedefineClasses__");

    // Parse the stream.
    Handle k_loader_h(THREAD, k_h->class_loader());
    Handle protection_domain;
    // Set redefined class handle in JvmtiThreadState class.
    // This redefined class is sent to agent event handler for class file
    // load hook event.
    state->set_class_being_redefined(&k_h);

    klassOop k = SystemDictionary::parse_stream(k_name, 
                                                k_loader_h, 
                                                protection_domain,
                                                &st,
                                                THREAD);
    // Clear class_being_redefined just to be sure.
    state->set_class_being_redefined(NULL);
                                     
    instanceKlassHandle k_h_new (THREAD, k);

    if (HAS_PENDING_EXCEPTION) {
      symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
      CLEAR_PENDING_EXCEPTION;

      if (ex_name == vmSymbols::java_lang_UnsupportedClassVersionError()) {
        return JVMTI_ERROR_UNSUPPORTED_VERSION;
      } else if (ex_name == vmSymbols::java_lang_ClassFormatError()) {
        return JVMTI_ERROR_INVALID_CLASS_FORMAT;
      } else if (ex_name == vmSymbols::java_lang_ClassCircularityError()) {
        return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION;
      } else if (ex_name == vmSymbols::java_lang_NoClassDefFoundError()) {
        // The message will be "XXX (wrong name: YYY)"
        return JVMTI_ERROR_NAMES_DONT_MATCH;
      } else {  // Just in case more exceptions can be thrown..
        return JVMTI_ERROR_FAILS_VERIFICATION;
      }
    }

    // All its super classes should be linked to 
    // initialize the vtable.
    instanceKlassHandle super(THREAD, k_h_new->super());
    if (super.not_null() && !super->is_linked()) {
      super->link_class(THREAD);
      if (HAS_PENDING_EXCEPTION) {
        CLEAR_PENDING_EXCEPTION;
        return JVMTI_ERROR_INTERNAL;
      }
    }
    
    // See instanceKlass::link_klass_impl()
    { ObjectLocker ol(k_h_new, THREAD);
      Verifier::verify_byte_codes(k_h_new, THREAD);

      if (HAS_PENDING_EXCEPTION) {
        CLEAR_PENDING_EXCEPTION;
        return JVMTI_ERROR_FAILS_VERIFICATION;
      }
      Rewriter::rewrite(k_h_new, THREAD);
      if (HAS_PENDING_EXCEPTION) {
        CLEAR_PENDING_EXCEPTION;
        return JVMTI_ERROR_INTERNAL;
      }
    }

    jvmtiError res = compare_class_versions(k_h, k_h_new);
    if (res != JVMTI_ERROR_NONE) return res;
  
    _k_h_new[i] = k_h_new;
  }
  
  return JVMTI_ERROR_NONE;
}
Exemplo n.º 2
0
  jvmdiError load_new_class_versions(TRAPS) {
    // For consistency allocate memory using os::malloc wrapper.
    _k_h_new = (instanceKlassHandle *) os::malloc(sizeof(instanceKlassHandle) * _class_count);

    ResourceMark rm(THREAD);

    for (int i = 0; i < _class_count; i++) {
      oop mirror = JNIHandles::resolve_non_null(_class_defs[i].clazz);
      klassOop k_oop = java_lang_Class::as_klassOop(mirror);
      instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop);
      symbolHandle k_name = symbolHandle(THREAD, k_h->name());

      ClassFileStream st((u1*) _class_defs[i].class_bytes, _class_defs[i].class_byte_count, NULL);

      // Parse the stream.
      Handle k_loader_h(THREAD, k_h->class_loader());
      Handle protection_domain;
      klassOop k = SystemDictionary::parse_stream(k_name, 
                                                  k_loader_h, 
                                                  protection_domain,
                                                  &st,
                                                  THREAD);
                                     
      instanceKlassHandle k_h_new (THREAD, k);

      if (HAS_PENDING_EXCEPTION) {
        if (PENDING_EXCEPTION->klass()->klass_part()->name() ==
          vmSymbols::java_lang_UnsupportedClassVersionError()) {
          CLEAR_PENDING_EXCEPTION;
          return JVMDI_ERROR_UNSUPPORTED_VERSION;

        } else if (PENDING_EXCEPTION->klass()->klass_part()->name() == 
          vmSymbols::java_lang_ClassFormatError()) {
          CLEAR_PENDING_EXCEPTION;
          return JVMDI_ERROR_INVALID_CLASS_FORMAT;
        } else if (PENDING_EXCEPTION->klass()->klass_part()->name() ==
          vmSymbols::java_lang_ClassCircularityError()) {
          CLEAR_PENDING_EXCEPTION;
          return JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION;
        } else if (PENDING_EXCEPTION->klass()->klass_part()->name() ==
          vmSymbols::java_lang_NoClassDefFoundError()) {
          // The message will be "XXX (wrong name: YYY)"
          CLEAR_PENDING_EXCEPTION;
          return JVMDI_ERROR_NAMES_DONT_MATCH;
        } else {  // Just in case more exceptions can be thrown..
          return JVMDI_ERROR_FAILS_VERIFICATION;
        }
      }

      // See instanceKlass::link_klass_impl()
      { ObjectLocker ol(k_h_new, THREAD);
        Verifier::verify_byte_codes(k_h_new, THREAD);

        if (HAS_PENDING_EXCEPTION) {
          CLEAR_PENDING_EXCEPTION;
          return JVMDI_ERROR_FAILS_VERIFICATION;
        }
        Rewriter::rewrite(k_h_new, THREAD); // No exception can happen here
      }

      jvmdiError res = compare_class_versions(k_h, k_h_new);
      if (res != JVMDI_ERROR_NONE) return res;
  
      _k_h_new[i] = k_h_new;
    }
  
    return JVMDI_ERROR_NONE;
  }