Esempio n. 1
0
// Begins stack walking.
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   skip_frames    Number of frames to be skipped.
//   frame_count    Number of frames to be traversed.
//   start_index    Start index to the user-supplied buffers.
//   frames_array   Buffer to store StackFrame in, starting at start_index.
//                  frames array is a Class<?>[] array when only getting caller
//                  reference, and a StackFrameInfo[] array (or derivative)
//                  otherwise. It should never be null.
//
// Returns Object returned from AbstractStackWalker::doStackWalk call.
//
oop StackWalk::walk(Handle stackStream, jlong mode,
                    int skip_frames, int frame_count, int start_index,
                    objArrayHandle frames_array,
                    TRAPS) {
    ResourceMark rm(THREAD);
    JavaThread* jt = (JavaThread*)THREAD;
    log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
                         mode, skip_frames, frame_count);

    if (frames_array.is_null()) {
        THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
    }

    // Setup traversal onto my stack.
    if (live_frame_info(mode)) {
        assert (use_frames_array(mode), "Bad mode for get live frame");
        RegisterMap regMap(jt, true);
        LiveFrameStream stream(jt, &regMap);
        return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
                               start_index, frames_array, THREAD);
    } else {
        JavaFrameStream stream(jt, mode);
        return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
                               start_index, frames_array, THREAD);
    }
}
Esempio n. 2
0
// Walk the next batch of stack frames
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   magic          Must be valid value to continue the stack walk
//   frame_count    Number of frames to be decoded.
//   start_index    Start index to the user-supplied buffers.
//   classes_array  Buffer to store classes in, starting at start_index.
//   frames_array   Buffer to store StackFrame in, starting at start_index.
//                  NULL if not used.
//
// Returns the end index of frame filled in the buffer.
//
jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
                           int frame_count, int start_index,
                           objArrayHandle classes_array,
                           objArrayHandle frames_array,
                           TRAPS)
{
  JavaThread* jt = (JavaThread*)THREAD;
  StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array);
  if (existing_anchor == NULL) {
    THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
  }

  if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) {
    THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
  }

  if (TraceStackWalk) {
    tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
                  frame_count, p2i(existing_anchor), start_index, classes_array->length());
  }
  int end_index = start_index;
  if (frame_count <= 0) {
    return end_index;        // No operation.
  }

  int count = frame_count + start_index;
  assert (classes_array->length() >= count, "not enough space in buffers");

  StackWalkAnchor& anchor = (*existing_anchor);
  vframeStream& vfst = anchor.vframe_stream();
  if (!vfst.at_end()) {
    vfst.next();  // this was the last frame decoded in the previous batch
    if (!vfst.at_end()) {
      int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array,
                             frames_array, end_index, CHECK_0);
      if (n < 1) {
        THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
      }
      return end_index;
    }
  }
  return end_index;
}
Esempio n. 3
0
// Walk the next batch of stack frames
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   magic          Must be valid value to continue the stack walk
//   frame_count    Number of frames to be decoded.
//   start_index    Start index to the user-supplied buffers.
//   frames_array   Buffer to store StackFrame in, starting at start_index.
//
// Returns the end index of frame filled in the buffer.
//
jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
                           int frame_count, int start_index,
                           objArrayHandle frames_array,
                           TRAPS)
{
  JavaThread* jt = (JavaThread*)THREAD;
  JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
  if (existing_stream == NULL) {
    THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
  }

  if (frames_array.is_null()) {
    THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
  }

  if (TraceStackWalk) {
    tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
                  frame_count, p2i(existing_stream), start_index, frames_array->length());
  }
  int end_index = start_index;
  if (frame_count <= 0) {
    return end_index;        // No operation.
  }

  int count = frame_count + start_index;
  assert (frames_array->length() >= count, "not enough space in buffers");

  JavaFrameStream& stream = (*existing_stream);
  if (!stream.at_end()) {
    stream.next(); // advance past the last frame decoded in previous batch
    if (!stream.at_end()) {
      int n = fill_in_frames(mode, stream, frame_count, start_index,
                             frames_array, end_index, CHECK_0);
      if (n < 1) {
        THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
      }
      return end_index;
    }
  }
  return end_index;
}
Esempio n. 4
0
oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
                               jlong mode, int skip_frames, int frame_count,
                               int start_index, objArrayHandle frames_array, TRAPS) {
    methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());

    {
        Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
        Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
        while (!stream.at_end()) {
            InstanceKlass* ik = stream.method()->method_holder();
            if (ik != stackWalker_klass &&
                    ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
                break;
            }

            if (log_is_enabled(Debug, stackwalk)) {
                ResourceMark rm(THREAD);
                outputStream* st = Log(stackwalk)::debug_stream();
                st->print("  skip ");
                stream.method()->print_short_name(st);
                st->cr();
            }
            stream.next();
        }

        // stack frame has been traversed individually and resume stack walk
        // from the stack frame at depth == skip_frames.
        for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
            if (log_is_enabled(Debug, stackwalk)) {
                ResourceMark rm(THREAD);
                outputStream* st = Log(stackwalk)::debug_stream();
                st->print("  skip ");
                stream.method()->print_short_name(st);
                st->cr();
            }
        }
    }

    int end_index = start_index;
    int numFrames = 0;
    if (!stream.at_end()) {
        numFrames = fill_in_frames(mode, stream, frame_count, start_index,
                                   frames_array, end_index, CHECK_NULL);
        if (numFrames < 1) {
            THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
        }
    }

    // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to
    // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
    // which calls the implementation to consume the stack frames.
    // When JVM_CallStackWalk returns, it invalidates the stack stream.
    JavaValue result(T_OBJECT);
    JavaCallArguments args(stackStream);
    args.push_long(stream.address_value());
    args.push_int(skip_frames);
    args.push_int(frame_count);
    args.push_int(start_index);
    args.push_int(end_index);

    // Link the thread and vframe stream into the callee-visible object
    stream.setup_magic_on_entry(frames_array);

    JavaCalls::call(&result, m_doStackWalk, &args, THREAD);

    // Do this before anything else happens, to disable any lingering stream objects
    bool ok = stream.cleanup_magic_on_exit(frames_array);

    // Throw pending exception if we must
    (void) (CHECK_NULL);

    if (!ok) {
        THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
    }

    // Return normally
    return (oop)result.get_jobject();
}
Esempio n. 5
0
// Begins stack walking.
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   skip_frames    Number of frames to be skipped.
//   frame_count    Number of frames to be traversed.
//   start_index    Start index to the user-supplied buffers.
//   classes_array  Buffer to store classes in, starting at start_index.
//   frames_array   Buffer to store StackFrame in, starting at start_index.
//                  NULL if not used.
//
// Returns Object returned from AbstractStackWalker::doStackWalk call.
//
oop StackWalk::walk(Handle stackStream, jlong mode,
                    int skip_frames, int frame_count, int start_index,
                    objArrayHandle classes_array,
                    objArrayHandle frames_array,
                    TRAPS) {
  JavaThread* jt = (JavaThread*)THREAD;
  if (TraceStackWalk) {
    tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
                  mode, skip_frames, frame_count);
  }

  if (need_method_info(mode)) {
    if (frames_array.is_null()) {
      THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
    }
  }

  Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
  Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();

  methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());

  // Open up a traversable stream onto my stack.
  // This stream will be made available by *reference* to the inner Java call.
  StackWalkAnchor anchor(jt);
  vframeStream& vfst = anchor.vframe_stream();

  {
    // Skip all methods from AbstractStackWalker and StackWalk (enclosing method)
    if (!fill_in_stacktrace(mode)) {
      while (!vfst.at_end()) {
        InstanceKlass* ik = vfst.method()->method_holder();
        if (ik != stackWalker_klass &&
              ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
          break;
        }

        if (TraceStackWalk) {
          tty->print("  skip "); vfst.method()->print_short_name(); tty->print("\n");
        }
        vfst.next();
      }
    }

    // For exceptions, skip Throwable::fillInStackTrace and <init> methods
    // of the exception class and superclasses
    if (fill_in_stacktrace(mode)) {
      bool skip_to_fillInStackTrace = false;
      bool skip_throwableInit_check = false;
      while (!vfst.at_end() && !skip_throwableInit_check) {
        InstanceKlass* ik = vfst.method()->method_holder();
        Method* method = vfst.method();
        if (!skip_to_fillInStackTrace) {
          if (ik == SystemDictionary::Throwable_klass() &&
              method->name() == vmSymbols::fillInStackTrace_name()) {
              // this frame will be skipped
              skip_to_fillInStackTrace = true;
          }
        } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) &&
                     method->name() == vmSymbols::object_initializer_name())) {
            // there are none or we've seen them all - either way stop checking
            skip_throwableInit_check = true;
            break;
        }

        if (TraceStackWalk) {
          tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n");
        }
        vfst.next();
      }
    }

    // stack frame has been traversed individually and resume stack walk
    // from the stack frame at depth == skip_frames.
    for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) {
      if (TraceStackWalk) {
        tty->print("  skip "); vfst.method()->print_short_name();
        tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
                      p2i(vfst.frame_id()), p2i(vfst.frame_pc()));
      }
    }
  }

  // The Method* pointer in the vfst has a very short shelf life.  Grab it now.
  int end_index = start_index;
  int numFrames = 0;
  if (!vfst.at_end()) {
    numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array,
                               frames_array, end_index, CHECK_NULL);
    if (numFrames < 1) {
      THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
    }
  }

  // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to
  // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
  // which calls the implementation to consume the stack frames.
  // When JVM_CallStackWalk returns, it invalidates the stack stream.
  JavaValue result(T_OBJECT);
  JavaCallArguments args(stackStream);
  args.push_long(anchor.address_value());
  args.push_int(skip_frames);
  args.push_int(frame_count);
  args.push_int(start_index);
  args.push_int(end_index);

  // Link the thread and vframe stream into the callee-visible object
  anchor.setup_magic_on_entry(classes_array);

  JavaCalls::call(&result, m_doStackWalk, &args, THREAD);

  // Do this before anything else happens, to disable any lingering stream objects
  bool ok = anchor.cleanup_magic_on_exit(classes_array);

  // Throw pending exception if we must
  (void) (CHECK_NULL);

  if (!ok) {
    THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
  }

  // Return normally
  return (oop)result.get_jobject();

}
Esempio n. 6
0
// Begins stack walking.
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   skip_frames    Number of frames to be skipped.
//   frame_count    Number of frames to be traversed.
//   start_index    Start index to the user-supplied buffers.
//   frames_array   Buffer to store StackFrame in, starting at start_index.
//                  frames array is a Class<?>[] array when only getting caller
//                  reference, and a StackFrameInfo[] array (or derivative)
//                  otherwise. It should never be null.
//
// Returns Object returned from AbstractStackWalker::doStackWalk call.
//
oop StackWalk::walk(Handle stackStream, jlong mode,
                    int skip_frames, int frame_count, int start_index,
                    objArrayHandle frames_array,
                    TRAPS) {
  ResourceMark rm(THREAD);
  JavaThread* jt = (JavaThread*)THREAD;
  if (TraceStackWalk) {
    tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
                  mode, skip_frames, frame_count);
  }

  if (frames_array.is_null()) {
    THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
  }

  Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
  Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();

  methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());

  // Setup traversal onto my stack.
  RegisterMap regMap(jt, true);
  JavaFrameStream stream(jt, &regMap);
  {
    while (!stream.at_end()) {
      InstanceKlass* ik = stream.method()->method_holder();
      if (ik != stackWalker_klass &&
            ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
        break;
      }

      if (TraceStackWalk) {
        tty->print("  skip "); stream.method()->print_short_name(); tty->print("\n");
      }
      stream.next();
    }

    // stack frame has been traversed individually and resume stack walk
    // from the stack frame at depth == skip_frames.
    for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
      if (TraceStackWalk) {
        tty->print("  skip "); stream.method()->print_short_name();
        tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
                      p2i(stream.java_frame()->fr().id()),
                      p2i(stream.java_frame()->fr().pc()));
      }
    }
  }

  int end_index = start_index;
  int numFrames = 0;
  if (!stream.at_end()) {
    numFrames = fill_in_frames(mode, stream, frame_count, start_index,
                               frames_array, end_index, CHECK_NULL);
    if (numFrames < 1) {
      THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
    }
  }

  // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to
  // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
  // which calls the implementation to consume the stack frames.
  // When JVM_CallStackWalk returns, it invalidates the stack stream.
  JavaValue result(T_OBJECT);
  JavaCallArguments args(stackStream);
  args.push_long(stream.address_value());
  args.push_int(skip_frames);
  args.push_int(frame_count);
  args.push_int(start_index);
  args.push_int(end_index);

  // Link the thread and vframe stream into the callee-visible object
  stream.setup_magic_on_entry(frames_array);

  JavaCalls::call(&result, m_doStackWalk, &args, THREAD);

  // Do this before anything else happens, to disable any lingering stream objects
  bool ok = stream.cleanup_magic_on_exit(frames_array);

  // Throw pending exception if we must
  (void) (CHECK_NULL);

  if (!ok) {
    THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
  }

  // Return normally
  return (oop)result.get_jobject();
}
Esempio n. 7
0
// Update child's copy of super vtable for overrides
// OR return true if a new vtable entry is required
// Only called for instanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
bool klassVtable::update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len,
                  bool checkconstraints, TRAPS) {
  ResourceMark rm;
  bool allocate_new = true;
  assert(klass->oop_is_instance(), "must be instanceKlass");

  // Initialize the method's vtable index to "nonvirtual".
  // If we allocate a vtable entry, we will update it to a non-negative number.
  target_method()->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);

  // Static and <init> methods are never in
  if (target_method()->is_static() || target_method()->name() ==  vmSymbols::object_initializer_name()) {
    return false;
  }

  if (klass->is_final() || target_method()->is_final()) {
    // a final method never needs a new entry; final methods can be statically
    // resolved and they have to be present in the vtable only if they override
    // a super's method, in which case they re-use its entry
    allocate_new = false;
  }

  // we need a new entry if there is no superclass
  if (klass->super() == NULL) {
    return allocate_new;
  }

  // private methods always have a new entry in the vtable
  // specification interpretation since classic has
  // private methods not overriding
  if (target_method()->is_private()) {
    return allocate_new;
  }

  // search through the vtable and update overridden entries
  // Since check_signature_loaders acquires SystemDictionary_lock
  // which can block for gc, once we are in this loop, use handles
  // For classfiles built with >= jdk7, we now look for transitive overrides

  Symbol* name = target_method()->name();
  Symbol* signature = target_method()->signature();
  Handle target_loader(THREAD, _klass->class_loader());
  Symbol*  target_classname = _klass->name();
  for(int i = 0; i < super_vtable_len; i++) {
    methodOop super_method = method_at(i);
    // Check if method name matches
    if (super_method->name() == name && super_method->signature() == signature) {

      // get super_klass for method_holder for the found method
      instanceKlass* super_klass =  instanceKlass::cast(super_method->method_holder());

      if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
      ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
        && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader,
             target_classname, THREAD)) != (instanceKlass*)NULL))) {
        // overriding, so no new entry
        allocate_new = false;

        if (checkconstraints) {
        // Override vtable entry if passes loader constraint check
        // if loader constraint checking requested
        // No need to visit his super, since he and his super
        // have already made any needed loader constraints.
        // Since loader constraints are transitive, it is enough
        // to link to the first super, and we get all the others.
          Handle super_loader(THREAD, super_klass->class_loader());

          if (target_loader() != super_loader()) {
            ResourceMark rm(THREAD);
            char* failed_type_name =
              SystemDictionary::check_signature_loaders(signature, target_loader,
                                                        super_loader, true,
                                                        CHECK_(false));
            if (failed_type_name != NULL) {
              const char* msg = "loader constraint violation: when resolving "
                "overridden method \"%s\" the class loader (instance"
                " of %s) of the current class, %s, and its superclass loader "
                "(instance of %s), have different Class objects for the type "
                "%s used in the signature";
              char* sig = target_method()->name_and_sig_as_C_string();
              const char* loader1 = SystemDictionary::loader_name(target_loader());
              char* current = _klass->name()->as_C_string();
              const char* loader2 = SystemDictionary::loader_name(super_loader());
              size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
                strlen(current) + strlen(loader2) + strlen(failed_type_name);
              char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
              jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
                           failed_type_name);
              THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false);
            }
          }
       }

        put_method_at(target_method(), i);
        target_method()->set_vtable_index(i);
#ifndef PRODUCT
        if (PrintVtables && Verbose) {
          tty->print("overriding with %s::%s index %d, original flags: ",
           _klass->internal_name(), (target_method() != NULL) ?
           target_method()->name()->as_C_string() : "<NULL>", i);
           super_method->access_flags().print_on(tty);
           tty->print("overriders flags: ");
           target_method->access_flags().print_on(tty);
           tty->cr();
        }
#endif /*PRODUCT*/
      } else {
// Update child's copy of super vtable for overrides
// OR return true if a new vtable entry is required
// Only called for instanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS) {    
  ResourceMark rm;
  bool allocate_new = true;
  assert(klass->oop_is_instance(), "must be instanceKlass");

  // Initialize the method's vtable index to "nonvirtual".
  // If we allocate a vtable entry, we will update it to a non-negative number.
  target_method()->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);

  // Static and <init> methods are never in 
  if (target_method()->is_static() || target_method()->name() ==  vmSymbols::object_initializer_name()) {
    return false;
  }

  if (klass->is_final() || target_method()->is_final()) {
    // a final method never needs a new entry; final methods can be statically
    // resolved and they have to be present in the vtable only if they override
    // a super's method, in which case they re-use its entry          
    allocate_new = false;
  }      

  // we need a new entry if there is no superclass
  if (klass->super() == NULL) {
    return allocate_new;
  }

  // private methods always have a new entry in the vtable
  if (target_method()->is_private()) {
    return allocate_new;
  }
  
  // search through the vtable and update overridden entries
  // Since check_signature_loaders acquires SystemDictionary_lock
  // which can block for gc, once we are in this loop, use handles, not
  // unhandled oops unless they are reinitialized for each loop
  // handles for name, signature, klass, target_method
  // not for match_method, holder
  
  symbolHandle name(THREAD,target_method()->name());
  symbolHandle signature(THREAD,target_method()->signature());    
  for(int i = 0; i < super_vtable_len; i++) {
    methodOop match_method = method_at(i);
    // Check if method name matches
    if (match_method->name() == name() && match_method->signature() == signature()) {
      
      instanceKlass* holder = (THREAD, instanceKlass::cast(match_method->method_holder()));

      // Check if the match_method is accessable from current class
      
      bool same_package_init = false;
      bool same_package_flag = false;
      bool simple_match = match_method->is_public()  || match_method->is_protected();
      if (!simple_match) {
        same_package_init = true;
        same_package_flag = holder->is_same_class_package(_klass->class_loader(), _klass->name());

        simple_match = match_method->is_package_private() && same_package_flag;
      }
      // match_method is the superclass' method. Note we can't override
      // and shouldn't access superclass' ACC_PRIVATE methods 
      // (although they have been copied into our vtable)
      // A simple form of this statement is:
      // if ( (match_method->is_public()  || match_method->is_protected()) ||
      //    (match_method->is_package_private() && holder->is_same_class_package(klass->class_loader(), klass->name()))) {
      //
      // The complexity is introduced it avoid recomputing 'is_same_class_package' which is expensive.
      if (simple_match) {      
        // Check if target_method and match_method has same level of accessibility. The accesibility of the
        // match method is the "most-general" visibility of all entries at it's particular vtable index for
        // all superclasses. This check must be done before we override the current entry in the vtable.
        AccessType at = vtable_accessibility_at(i);        
        bool same_access = false;

        if (  (at == acc_publicprotected && (target_method()->is_public() || target_method()->is_protected())) 
           || (at == acc_package_private && (target_method()->is_package_private() &&
                                            (( same_package_init && same_package_flag) ||
(!same_package_init&&holder->is_same_class_package(_klass->class_loader(),_klass->name())))))){
           same_access = true;
        }
        
        if (checkconstraints) {
        // Override vtable entry if passes loader constraint check
        // if loader constraint checking requested
        // No need to visit his super, since he and his super
        // have already made any needed loader constraints.
        // Since loader constraints are transitive, it is enough
        // to link to the first super, and we get all the others.
          symbolHandle signature(THREAD, target_method()->signature());
          Handle this_loader(THREAD, _klass->class_loader());
          instanceKlassHandle super_klass(THREAD, _klass->super());
          Handle super_loader(THREAD, super_klass->class_loader());

          if (this_loader() != super_loader()) {
	    ResourceMark rm(THREAD);
            char* failed_type_name = 
	      SystemDictionary::check_signature_loaders(signature, this_loader,
							super_loader, true, 
							CHECK_(false));
	    if (failed_type_name != NULL) {
	      const char* msg = "loader constraint violation: when resolving "
		"overridden method \"%s\" the class loader (instance"
		" of %s) of the current class, %s, and its superclass loader "
		"(instance of %s), have different Class objects for the type "
		"%s used in the signature";
	      char* sig = target_method()->name_and_sig_as_C_string();
	      const char* loader1 = SystemDictionary::loader_name(this_loader());
	      char* current = _klass->name()->as_C_string();
	      const char* loader2 = SystemDictionary::loader_name(super_loader());
	      size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + 
		strlen(current) + strlen(loader2) + strlen(failed_type_name);
	      char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
	      jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
			   failed_type_name);
	      THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false);
	    }
          }
        }
        put_method_at(target_method(), i);


        if (same_access) {
          // target and match has same accessiblity - share entry  
          allocate_new = false;
          target_method()->set_vtable_index(i);
#ifndef PRODUCT
          if (PrintVtables && Verbose) {  
            AccessType targetacc; 
            if (target_method()->is_protected() || 
                 target_method()->is_public()) {
               targetacc =  acc_publicprotected;
            } else {
              targetacc = target_method()->is_package_private() ? acc_package_private : acc_private;
            }
            tty->print_cr("overriding with %s::%s index %d, original flags: %x overriders flags: %x", 
             _klass->internal_name(), (target_method() != NULL) ? 
             target_method()->name()->as_C_string() : "<NULL>", i,
             at, targetacc);
          }
#endif /*PRODUCT*/
        } else {
#ifndef PRODUCT
          if (PrintVtables && Verbose) {  
            AccessType targetacc; 
            if (target_method()->is_protected() || 
                 target_method()->is_public()) {
               targetacc =  acc_publicprotected;
            } else {
              targetacc = target_method()->is_package_private() ? acc_package_private : acc_private;
            }
            tty->print_cr("override %s %s::%s at index %d, original flags: %x overriders flags: %x", 
            allocate_new ? "+ new" : "only",
            _klass->internal_name(), (target_method() != NULL) ? 
            target_method()->name()->as_C_string() : "<NULL>", i,
            at, targetacc);
           }
#endif /*PRODUCT*/
        }
      }
    }