コード例 #1
0
ファイル: klassFactory.cpp プロジェクト: lmsf/jdk9-dev
static ClassFileStream* prologue(ClassFileStream* stream,
                                 Symbol* name,
                                 ClassLoaderData* loader_data,
                                 Handle protection_domain,
                                 JvmtiCachedClassFileData** cached_class_file,
                                 TRAPS) {

  assert(stream != NULL, "invariant");

  if (JvmtiExport::should_post_class_file_load_hook()) {
    assert(THREAD->is_Java_thread(), "must be a JavaThread");
    const JavaThread* jt = (JavaThread*)THREAD;

    Handle class_loader(THREAD, loader_data->class_loader());

    // Get the cached class file bytes (if any) from the class that
    // is being redefined or retransformed. We use jvmti_thread_state()
    // instead of JvmtiThreadState::state_for(jt) so we don't allocate
    // a JvmtiThreadState any earlier than necessary. This will help
    // avoid the bug described by 7126851.

    JvmtiThreadState* state = jt->jvmti_thread_state();

    if (state != NULL) {
      KlassHandle* h_class_being_redefined =
        state->get_class_being_redefined();

      if (h_class_being_redefined != NULL) {
        instanceKlassHandle ikh_class_being_redefined =
          instanceKlassHandle(THREAD, (*h_class_being_redefined)());

        *cached_class_file = ikh_class_being_redefined->get_cached_class_file();
      }
    }

    unsigned char* ptr = const_cast<unsigned char*>(stream->buffer());
    unsigned char* end_ptr = ptr + stream->length();

    JvmtiExport::post_class_file_load_hook(name,
                                           class_loader,
                                           protection_domain,
                                           &ptr,
                                           &end_ptr,
                                           cached_class_file);

    if (ptr != stream->buffer()) {
      // JVMTI agent has modified class file data.
      // Set new class file stream using JVMTI agent modified class file data.
      stream = new ClassFileStream(ptr,
                                   end_ptr - ptr,
                                   stream->source(),
                                   stream->need_verify());
    }
  }

  return stream;
}
コード例 #2
0
void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
  ((methodOopDesc*)_method->*meth_act)(_bci);

  // add/remove breakpoint to/from versions of the method that
  // are EMCP. Directly or transitively obsolete methods are
  // not saved in the PreviousVersionInfo.
  Thread *thread = Thread::current();
  instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
  Symbol* m_name = _method->name();
  Symbol* m_signature = _method->signature();

  {
    ResourceMark rm(thread);
    // PreviousVersionInfo objects returned via PreviousVersionWalker
    // contain a GrowableArray of handles. We have to clean up the
    // GrowableArray _after_ the PreviousVersionWalker destructor
    // has destroyed the handles.
    {
      // search previous versions if they exist
      PreviousVersionWalker pvw((instanceKlass *)ikh()->klass_part());
      for (PreviousVersionInfo * pv_info = pvw.next_previous_version();
           pv_info != NULL; pv_info = pvw.next_previous_version()) {
        GrowableArray<methodHandle>* methods =
          pv_info->prev_EMCP_method_handles();

        if (methods == NULL) {
          // We have run into a PreviousVersion generation where
          // all methods were made obsolete during that generation's
          // RedefineClasses() operation. At the time of that
          // operation, all EMCP methods were flushed so we don't
          // have to go back any further.
          //
          // A NULL methods array is different than an empty methods
          // array. We cannot infer any optimizations about older
          // generations from an empty methods array for the current
          // generation.
          break;
        }

        for (int i = methods->length() - 1; i >= 0; i--) {
          methodHandle method = methods->at(i);
          if (method->name() == m_name && method->signature() == m_signature) {
            RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
              meth_act == &methodOopDesc::set_breakpoint ? "sett" : "clear",
              method->name()->as_C_string(),
              method->signature()->as_C_string()));
            assert(!method->is_obsolete(), "only EMCP methods here");

            ((methodOopDesc*)method()->*meth_act)(_bci);
            break;
          }
        }
      }
    } // pvw is cleaned up
  } // rm is cleaned up
}
コード例 #3
0
ファイル: classLoaderExt.hpp プロジェクト: gaoxiaojun/dync
 instanceKlassHandle record_result(const int classpath_index,
                                   const ClassPathEntry* e,
                                   instanceKlassHandle result, TRAPS) {
   if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
     if (DumpSharedSpaces) {
       result->set_shared_classpath_index(classpath_index);
     }
     return result;
   } else {
     return instanceKlassHandle(); // NULL
   }
 }
コード例 #4
0
void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
  ((Method*)_method->*meth_act)(_bci);

  // add/remove breakpoint to/from versions of the method that
  // are EMCP. Directly or transitively obsolete methods are
  // not saved in the PreviousVersionNodes.
  Thread *thread = Thread::current();
  instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
  Symbol* m_name = _method->name();
  Symbol* m_signature = _method->signature();

  // search previous versions if they exist
  PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
       pv_node != NULL; pv_node = pvw.next_previous_version()) {
    GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();

    if (methods == NULL) {
      // We have run into a PreviousVersion generation where
      // all methods were made obsolete during that generation's
      // RedefineClasses() operation. At the time of that
      // operation, all EMCP methods were flushed so we don't
      // have to go back any further.
      //
      // A NULL methods array is different than an empty methods
      // array. We cannot infer any optimizations about older
      // generations from an empty methods array for the current
      // generation.
      break;
    }

    for (int i = methods->length() - 1; i >= 0; i--) {
      Method* method = methods->at(i);
      // obsolete methods that are running are not deleted from
      // previous version array, but they are skipped here.
      if (!method->is_obsolete() &&
          method->name() == m_name &&
          method->signature() == m_signature) {
        RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
          meth_act == &Method::set_breakpoint ? "sett" : "clear",
          method->name()->as_C_string(),
          method->signature()->as_C_string()));

        (method->*meth_act)(_bci);
        break;
      }
    }
  }
}
コード例 #5
0
// Install the redefinition of a class --
// The original instanceKlass object (k_h) always represents the latest 
// version of the respective class. However, during class redefinition we swap
// or replace much of its content with that of the instanceKlass object created
// from the bytes of the redefine (k_h_new). Specifically, k_h points to the new
// constantpool and methods objects, which we take from k_h_new. k_h_new, in turn,
// assumes the role of the previous class version, with the old constantpool and
// methods (taken from k_h) attached to it. k_h links to k_h_new to create a 
// linked list of class versions. 
void VM_RedefineClasses::redefine_single_class(jclass j_clazz, instanceKlassHandle k_h_new, TRAPS) {

  oop mirror = JNIHandles::resolve_non_null(j_clazz);
  klassOop k_oop = java_lang_Class::as_klassOop(mirror);
  instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop);

  // Remove all breakpoints in methods of this class
  JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
  jvmti_breakpoints.clearall_in_class_at_safepoint(k_oop); 

  // Deoptimize all compiled code that depends on this class
  NOT_CORE(Universe::flush_evol_dependents_on(k_h));

  _old_methods = k_h->methods();
  _new_methods = k_h_new->methods();
  _evolving_koop = k_oop;
  _old_constants = k_h->constants();

  // flush the cached jmethodID fields for _old_methods
  flush_method_jmethod_id_cache();

  // Patch the indexes into the constantpool from the array of fields of the evolving
  // class. This is required, because the layout of the new constantpool can be different,
  // so old indexes corresponding to field names and signatures can become invalid.
  patch_indexes_for_fields(k_h, k_h_new);

  // Make new constantpool object (and methodOops via it) point to the original class object
  k_h_new->constants()->set_pool_holder(k_h());

  // Replace methods and constantpool
  k_h->set_methods(_new_methods);
  k_h_new->set_methods(_old_methods);     // To prevent potential GCing of the old methods, 
                                          // and to be able to undo operation easily.

  constantPoolOop old_constants = k_h->constants();
  k_h->set_constants(k_h_new->constants());
  k_h_new->set_constants(old_constants);  // See the previous comment.

  check_methods_and_mark_as_old();
  transfer_old_native_function_registrations();

  // Replace inner_classes
  typeArrayOop old_inner_classes = k_h->inner_classes();
  k_h->set_inner_classes(k_h_new->inner_classes());
  k_h_new->set_inner_classes(old_inner_classes);

  // Initialize the vtable and interface table after
  // methods have been rewritten
  { ResourceMark rm(THREAD);
  k_h->vtable()->initialize_vtable(THREAD); // No exception can happen here
  k_h->itable()->initialize_itable();
  }

  // Copy the "source file name" attribute from new class version
  k_h->set_source_file_name(k_h_new->source_file_name());

  // Copy the "source debug extension" attribute from new class version
  k_h->set_source_debug_extension(k_h_new->source_debug_extension());

  // Use of javac -g could be different in the old and the new
  if (k_h_new->access_flags().has_localvariable_table() !=
      k_h->access_flags().has_localvariable_table()) {

    AccessFlags flags = k_h->access_flags();
    if (k_h_new->access_flags().has_localvariable_table()) {
      flags.set_has_localvariable_table();
    } else {
      flags.clear_has_localvariable_table();
    }
    k_h->set_access_flags(flags);
  }

  // Replace class annotation fields values
  typeArrayOop old_class_annotations = k_h->class_annotations();
  k_h->set_class_annotations(k_h_new->class_annotations());
  k_h_new->set_class_annotations(old_class_annotations);

  // Replace fields annotation fields values
  objArrayOop old_fields_annotations = k_h->fields_annotations();
  k_h->set_fields_annotations(k_h_new->fields_annotations());
  k_h_new->set_fields_annotations(old_fields_annotations);

  // Replace methods annotation fields values
  objArrayOop old_methods_annotations = k_h->methods_annotations();
  k_h->set_methods_annotations(k_h_new->methods_annotations());
  k_h_new->set_methods_annotations(old_methods_annotations);

  // Replace methods parameter annotation fields values
  objArrayOop old_methods_parameter_annotations = k_h->methods_parameter_annotations();
  k_h->set_methods_parameter_annotations(k_h_new->methods_parameter_annotations());
  k_h_new->set_methods_parameter_annotations(old_methods_parameter_annotations);

  // Replace methods default annotation fields values
  objArrayOop old_methods_default_annotations = k_h->methods_default_annotations();
  k_h->set_methods_default_annotations(k_h_new->methods_default_annotations());
  k_h_new->set_methods_default_annotations(old_methods_default_annotations);

  // Replace major version number of class file
  u2 old_major_version = k_h->major_version();
  k_h->set_major_version(k_h_new->major_version());
  k_h_new->set_major_version(old_major_version);

  // Replace CP indexes for class and name+type of enclosing method
  u2 old_class_idx  = k_h->enclosing_method_class_index();
  u2 old_method_idx = k_h->enclosing_method_method_index();
  k_h->set_enclosing_method_indices(k_h_new->enclosing_method_class_index(),
                                    k_h_new->enclosing_method_method_index());
  k_h_new->set_enclosing_method_indices(old_class_idx, old_method_idx);

  // Maintain a linked list of versions of this class. 
  // List is in ascending age order. Current version (k_h) is the head.
  if (k_h->has_previous_version()) {
    k_h_new->set_previous_version(k_h->previous_version());
  }
  k_h->set_previous_version(k_h_new);

  // Adjust constantpool caches and vtables for all classes
  // that reference methods of the evolved class.
  SystemDictionary::classes_do(adjust_cpool_cache_and_vtable);
  k_h->set_rewritten_by_redefine(true);
}
コード例 #6
0
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;
}
コード例 #7
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;
  }