8023697: failed class resolution reports different class name in detail message for the first and subsequent times

Mon, 05 May 2014 19:53:00 -0400

author
coleenp
date
Mon, 05 May 2014 19:53:00 -0400
changeset 9966
baf9f57c9b46
parent 9965
c39172598323
child 9967
7ada1402bda0

8023697: failed class resolution reports different class name in detail message for the first and subsequent times
Summary: Cache detail message when we cache exception for constant pool resolution.
Reviewed-by: acorn, twisti, jrose

src/share/vm/classfile/resolutionErrors.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/resolutionErrors.hpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/systemDictionary.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/systemDictionary.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/constantPool.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/constantPool.hpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/constantTag.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/constantTag.hpp file | annotate | diff | comparison | revisions
test/runtime/ClassResolutionFail/Property.java file | annotate | diff | comparison | revisions
test/runtime/ClassResolutionFail/PropertySuper.java file | annotate | diff | comparison | revisions
test/runtime/ClassResolutionFail/TestClassResolutionFail.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/resolutionErrors.cpp	Mon Mar 23 17:57:13 2020 +0000
     1.2 +++ b/src/share/vm/classfile/resolutionErrors.cpp	Mon May 05 19:53:00 2014 -0400
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -32,12 +32,13 @@
    1.11  
    1.12  // add new entry to the table
    1.13  void ResolutionErrorTable::add_entry(int index, unsigned int hash,
    1.14 -                                     constantPoolHandle pool, int cp_index, Symbol* error)
    1.15 +                                     constantPoolHandle pool, int cp_index,
    1.16 +                                     Symbol* error, Symbol* message)
    1.17  {
    1.18    assert_locked_or_safepoint(SystemDictionary_lock);
    1.19    assert(!pool.is_null() && error != NULL, "adding NULL obj");
    1.20  
    1.21 -  ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error);
    1.22 +  ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error, message);
    1.23    add_entry(index, entry);
    1.24  }
    1.25  
    1.26 @@ -58,19 +59,26 @@
    1.27  }
    1.28  
    1.29  void ResolutionErrorEntry::set_error(Symbol* e) {
    1.30 -  assert(e == NULL || _error == NULL, "cannot reset error");
    1.31 +  assert(e != NULL, "must set a value");
    1.32    _error = e;
    1.33 -  if (_error != NULL) _error->increment_refcount();
    1.34 +  _error->increment_refcount();
    1.35 +}
    1.36 +
    1.37 +void ResolutionErrorEntry::set_message(Symbol* c) {
    1.38 +  assert(c != NULL, "must set a value");
    1.39 +  _message = c;
    1.40 +  _message->increment_refcount();
    1.41  }
    1.42  
    1.43  // create new error entry
    1.44  ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, ConstantPool* pool,
    1.45 -                                                      int cp_index, Symbol* error)
    1.46 +                                                      int cp_index, Symbol* error,
    1.47 +                                                      Symbol* message)
    1.48  {
    1.49    ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool);
    1.50    entry->set_cp_index(cp_index);
    1.51 -  NOT_PRODUCT(entry->set_error(NULL);)
    1.52    entry->set_error(error);
    1.53 +  entry->set_message(message);
    1.54  
    1.55    return entry;
    1.56  }
    1.57 @@ -79,6 +87,7 @@
    1.58    // decrement error refcount
    1.59    assert(entry->error() != NULL, "error should be set");
    1.60    entry->error()->decrement_refcount();
    1.61 +  entry->message()->decrement_refcount();
    1.62    Hashtable<ConstantPool*, mtClass>::free_entry(entry);
    1.63  }
    1.64  
     2.1 --- a/src/share/vm/classfile/resolutionErrors.hpp	Mon Mar 23 17:57:13 2020 +0000
     2.2 +++ b/src/share/vm/classfile/resolutionErrors.hpp	Mon May 05 19:53:00 2014 -0400
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -38,7 +38,8 @@
    2.11  public:
    2.12    ResolutionErrorTable(int table_size);
    2.13  
    2.14 -  ResolutionErrorEntry* new_entry(int hash, ConstantPool* pool, int cp_index, Symbol* error);
    2.15 +  ResolutionErrorEntry* new_entry(int hash, ConstantPool* pool, int cp_index,
    2.16 +                                  Symbol* error, Symbol* message);
    2.17    void free_entry(ResolutionErrorEntry *entry);
    2.18  
    2.19    ResolutionErrorEntry* bucket(int i) {
    2.20 @@ -55,7 +56,7 @@
    2.21    }
    2.22  
    2.23    void add_entry(int index, unsigned int hash,
    2.24 -                 constantPoolHandle pool, int which, Symbol* error);
    2.25 +                 constantPoolHandle pool, int which, Symbol* error, Symbol* message);
    2.26  
    2.27  
    2.28    // find error given the constant pool and constant pool index
    2.29 @@ -79,10 +80,10 @@
    2.30   private:
    2.31    int               _cp_index;
    2.32    Symbol*           _error;
    2.33 +  Symbol*           _message;
    2.34  
    2.35   public:
    2.36 -  ConstantPool*      pool() const               { return (ConstantPool*)literal(); }
    2.37 -  ConstantPool**   pool_addr()                { return (ConstantPool**)literal_addr(); }
    2.38 +  ConstantPool*      pool() const               { return literal(); }
    2.39  
    2.40    int                cp_index() const           { return _cp_index; }
    2.41    void               set_cp_index(int cp_index) { _cp_index = cp_index; }
    2.42 @@ -90,6 +91,9 @@
    2.43    Symbol*            error() const              { return _error; }
    2.44    void               set_error(Symbol* e);
    2.45  
    2.46 +  Symbol*            message() const            { return _message; }
    2.47 +  void               set_message(Symbol* c);
    2.48 +
    2.49    ResolutionErrorEntry* next() const {
    2.50      return (ResolutionErrorEntry*)HashtableEntry<ConstantPool*, mtClass>::next();
    2.51    }
     3.1 --- a/src/share/vm/classfile/systemDictionary.cpp	Mon Mar 23 17:57:13 2020 +0000
     3.2 +++ b/src/share/vm/classfile/systemDictionary.cpp	Mon May 05 19:53:00 2014 -0400
     3.3 @@ -185,12 +185,14 @@
     3.4    if (HAS_PENDING_EXCEPTION || klass == NULL) {
     3.5      KlassHandle k_h(THREAD, klass);
     3.6      // can return a null klass
     3.7 -    klass = handle_resolution_exception(class_name, class_loader, protection_domain, throw_error, k_h, THREAD);
     3.8 +    klass = handle_resolution_exception(class_name, throw_error, k_h, THREAD);
     3.9    }
    3.10    return klass;
    3.11  }
    3.12  
    3.13 -Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS) {
    3.14 +Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name,
    3.15 +                                                     bool throw_error,
    3.16 +                                                     KlassHandle klass_h, TRAPS) {
    3.17    if (HAS_PENDING_EXCEPTION) {
    3.18      // If we have a pending exception we forward it to the caller, unless throw_error is true,
    3.19      // in which case we have to check whether the pending exception is a ClassNotFoundException,
    3.20 @@ -398,7 +400,7 @@
    3.21    }
    3.22    if (HAS_PENDING_EXCEPTION || superk_h() == NULL) {
    3.23      // can null superk
    3.24 -    superk_h = KlassHandle(THREAD, handle_resolution_exception(class_name, class_loader, protection_domain, true, superk_h, THREAD));
    3.25 +    superk_h = KlassHandle(THREAD, handle_resolution_exception(class_name, true, superk_h, THREAD));
    3.26    }
    3.27  
    3.28    return superk_h();
    3.29 @@ -2246,12 +2248,13 @@
    3.30  
    3.31  // Add entry to resolution error table to record the error when the first
    3.32  // attempt to resolve a reference to a class has failed.
    3.33 -void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which, Symbol* error) {
    3.34 +void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which,
    3.35 +                                            Symbol* error, Symbol* message) {
    3.36    unsigned int hash = resolution_errors()->compute_hash(pool, which);
    3.37    int index = resolution_errors()->hash_to_index(hash);
    3.38    {
    3.39      MutexLocker ml(SystemDictionary_lock, Thread::current());
    3.40 -    resolution_errors()->add_entry(index, hash, pool, which, error);
    3.41 +    resolution_errors()->add_entry(index, hash, pool, which, error, message);
    3.42    }
    3.43  }
    3.44  
    3.45 @@ -2261,13 +2264,19 @@
    3.46  }
    3.47  
    3.48  // Lookup resolution error table. Returns error if found, otherwise NULL.
    3.49 -Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which) {
    3.50 +Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which,
    3.51 +                                                Symbol** message) {
    3.52    unsigned int hash = resolution_errors()->compute_hash(pool, which);
    3.53    int index = resolution_errors()->hash_to_index(hash);
    3.54    {
    3.55      MutexLocker ml(SystemDictionary_lock, Thread::current());
    3.56      ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
    3.57 -    return (entry != NULL) ? entry->error() : (Symbol*)NULL;
    3.58 +    if (entry != NULL) {
    3.59 +      *message = entry->message();
    3.60 +      return entry->error();
    3.61 +    } else {
    3.62 +      return NULL;
    3.63 +    }
    3.64    }
    3.65  }
    3.66  
     4.1 --- a/src/share/vm/classfile/systemDictionary.hpp	Mon Mar 23 17:57:13 2020 +0000
     4.2 +++ b/src/share/vm/classfile/systemDictionary.hpp	Mon May 05 19:53:00 2014 -0400
     4.3 @@ -241,7 +241,7 @@
     4.4    static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS);
     4.5  protected:
     4.6    // handle error translation for resolve_or_null results
     4.7 -  static Klass* handle_resolution_exception(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS);
     4.8 +  static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, KlassHandle klass_h, TRAPS);
     4.9  
    4.10  public:
    4.11  
    4.12 @@ -549,9 +549,11 @@
    4.13  
    4.14    // Record the error when the first attempt to resolve a reference from a constant
    4.15    // pool entry to a class fails.
    4.16 -  static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error);
    4.17 +  static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error,
    4.18 +                                   Symbol* message);
    4.19    static void delete_resolution_error(ConstantPool* pool);
    4.20 -  static Symbol* find_resolution_error(constantPoolHandle pool, int which);
    4.21 +  static Symbol* find_resolution_error(constantPoolHandle pool, int which,
    4.22 +                                       Symbol** message);
    4.23  
    4.24   protected:
    4.25  
     5.1 --- a/src/share/vm/oops/constantPool.cpp	Mon Mar 23 17:57:13 2020 +0000
     5.2 +++ b/src/share/vm/oops/constantPool.cpp	Mon May 05 19:53:00 2014 -0400
     5.3 @@ -235,14 +235,14 @@
     5.4  
     5.5  
     5.6    // The original attempt to resolve this constant pool entry failed so find the
     5.7 -  // original error and throw it again (JVMS 5.4.3).
     5.8 +  // class of the original error and throw another error of the same class (JVMS 5.4.3).
     5.9 +  // If there is a detail message, pass that detail message to the error constructor.
    5.10 +  // The JVMS does not strictly require us to duplicate the same detail message,
    5.11 +  // or any internal exception fields such as cause or stacktrace.  But since the
    5.12 +  // detail message is often a class name or other literal string, we will repeat it if
    5.13 +  // we can find it in the symbol table.
    5.14    if (in_error) {
    5.15 -    Symbol* error = SystemDictionary::find_resolution_error(this_oop, which);
    5.16 -    guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
    5.17 -    ResourceMark rm;
    5.18 -    // exception text will be the class name
    5.19 -    const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
    5.20 -    THROW_MSG_0(error, className);
    5.21 +    throw_resolution_error(this_oop, which, CHECK_0);
    5.22    }
    5.23  
    5.24    if (do_resolve) {
    5.25 @@ -262,11 +262,6 @@
    5.26      // Failed to resolve class. We must record the errors so that subsequent attempts
    5.27      // to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
    5.28      if (HAS_PENDING_EXCEPTION) {
    5.29 -      ResourceMark rm;
    5.30 -      Symbol* error = PENDING_EXCEPTION->klass()->name();
    5.31 -
    5.32 -      bool throw_orig_error = false;
    5.33 -      {
    5.34          MonitorLockerEx ml(this_oop->lock());
    5.35  
    5.36          // some other thread has beaten us and has resolved the class.
    5.37 @@ -276,32 +271,9 @@
    5.38            return entry.get_klass();
    5.39          }
    5.40  
    5.41 -        if (!PENDING_EXCEPTION->
    5.42 -              is_a(SystemDictionary::LinkageError_klass())) {
    5.43 -          // Just throw the exception and don't prevent these classes from
    5.44 -          // being loaded due to virtual machine errors like StackOverflow
    5.45 -          // and OutOfMemoryError, etc, or if the thread was hit by stop()
    5.46 -          // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
    5.47 -        }
    5.48 -        else if (!this_oop->tag_at(which).is_unresolved_klass_in_error()) {
    5.49 -          SystemDictionary::add_resolution_error(this_oop, which, error);
    5.50 -          this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
    5.51 -        } else {
    5.52 -          // some other thread has put the class in error state.
    5.53 -          error = SystemDictionary::find_resolution_error(this_oop, which);
    5.54 -          assert(error != NULL, "checking");
    5.55 -          throw_orig_error = true;
    5.56 -        }
    5.57 -      } // unlocked
    5.58 -
    5.59 -      if (throw_orig_error) {
    5.60 -        CLEAR_PENDING_EXCEPTION;
    5.61 -        ResourceMark rm;
    5.62 -        const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
    5.63 -        THROW_MSG_0(error, className);
    5.64 -      }
    5.65 -
    5.66 -      return 0;
    5.67 +        // The tag could have changed to in-error before the lock but we have to
    5.68 +        // handle that here for the class case.
    5.69 +        save_and_throw_exception(this_oop, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0);
    5.70      }
    5.71  
    5.72      if (TraceClassResolution && !k()->oop_is_array()) {
    5.73 @@ -597,16 +569,55 @@
    5.74    return true;
    5.75  }
    5.76  
    5.77 -// If resolution for MethodHandle or MethodType fails, save the exception
    5.78 +Symbol* ConstantPool::exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception) {
    5.79 +  // Dig out the detailed message to reuse if possible
    5.80 +  Symbol* message = NULL;
    5.81 +  oop detailed_message = java_lang_Throwable::message(pending_exception);
    5.82 +  if (detailed_message != NULL) {
    5.83 +     message = java_lang_String::as_symbol_or_null(detailed_message);
    5.84 +     if (message != NULL) {
    5.85 +       return message;
    5.86 +     }
    5.87 +  }
    5.88 +
    5.89 +  // Return specific message for the tag
    5.90 +  switch (tag.value()) {
    5.91 +  case JVM_CONSTANT_UnresolvedClass:
    5.92 +    // return the class name in the error message
    5.93 +    message = this_oop->unresolved_klass_at(which);
    5.94 +    break;
    5.95 +  case JVM_CONSTANT_MethodHandle:
    5.96 +    // return the method handle name in the error message
    5.97 +    message = this_oop->method_handle_name_ref_at(which);
    5.98 +    break;
    5.99 +  case JVM_CONSTANT_MethodType:
   5.100 +    // return the method type signature in the error message
   5.101 +    message = this_oop->method_type_signature_at(which);
   5.102 +    break;
   5.103 +  default:
   5.104 +    ShouldNotReachHere();
   5.105 +  }
   5.106 +
   5.107 +  return message;
   5.108 +}
   5.109 +
   5.110 +void ConstantPool::throw_resolution_error(constantPoolHandle this_oop, int which, TRAPS) {
   5.111 +  Symbol* message = NULL;
   5.112 +  Symbol* error = SystemDictionary::find_resolution_error(this_oop, which, &message);
   5.113 +  assert(error != NULL && message != NULL, "checking");
   5.114 +  CLEAR_PENDING_EXCEPTION;
   5.115 +  ResourceMark rm;
   5.116 +  THROW_MSG(error, message->as_C_string());
   5.117 +}
   5.118 +
   5.119 +// If resolution for Class, MethodHandle or MethodType fails, save the exception
   5.120  // in the resolution error table, so that the same exception is thrown again.
   5.121  void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which,
   5.122 -                                     int tag, TRAPS) {
   5.123 -  ResourceMark rm;
   5.124 +                                            constantTag tag, TRAPS) {
   5.125 +  assert(this_oop->lock()->is_locked(), "constant pool lock should be held");
   5.126    Symbol* error = PENDING_EXCEPTION->klass()->name();
   5.127 -  MonitorLockerEx ml(this_oop->lock());  // lock cpool to change tag.
   5.128  
   5.129 -  int error_tag = (tag == JVM_CONSTANT_MethodHandle) ?
   5.130 -           JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError;
   5.131 +  int error_tag = tag.error_value();
   5.132  
   5.133    if (!PENDING_EXCEPTION->
   5.134      is_a(SystemDictionary::LinkageError_klass())) {
   5.135 @@ -614,20 +625,21 @@
   5.136      // being loaded due to virtual machine errors like StackOverflow
   5.137      // and OutOfMemoryError, etc, or if the thread was hit by stop()
   5.138      // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
   5.139 -
   5.140    } else if (this_oop->tag_at(which).value() != error_tag) {
   5.141 -    SystemDictionary::add_resolution_error(this_oop, which, error);
   5.142 +    Symbol* message = exception_message(this_oop, which, tag, PENDING_EXCEPTION);
   5.143 +    SystemDictionary::add_resolution_error(this_oop, which, error, message);
   5.144      this_oop->tag_at_put(which, error_tag);
   5.145    } else {
   5.146 -    // some other thread has put the class in error state.
   5.147 -    error = SystemDictionary::find_resolution_error(this_oop, which);
   5.148 -    assert(error != NULL, "checking");
   5.149 -    CLEAR_PENDING_EXCEPTION;
   5.150 -    THROW_MSG(error, "");
   5.151 +    // some other thread put this in error state
   5.152 +    throw_resolution_error(this_oop, which, CHECK);
   5.153    }
   5.154 +
   5.155 +  // This exits with some pending exception
   5.156 +  assert(HAS_PENDING_EXCEPTION, "should not be cleared");
   5.157  }
   5.158  
   5.159  
   5.160 +
   5.161  // Called to resolve constants in the constant pool and return an oop.
   5.162  // Some constant pool entries cache their resolved oop. This is also
   5.163  // called to create oops from constants to use in arguments for invokedynamic
   5.164 @@ -655,9 +667,9 @@
   5.165  
   5.166    jvalue prim_value;  // temp used only in a few cases below
   5.167  
   5.168 -  int tag_value = this_oop->tag_at(index).value();
   5.169 +  constantTag tag = this_oop->tag_at(index);
   5.170  
   5.171 -  switch (tag_value) {
   5.172 +  switch (tag.value()) {
   5.173  
   5.174    case JVM_CONSTANT_UnresolvedClass:
   5.175    case JVM_CONSTANT_UnresolvedClassInError:
   5.176 @@ -682,10 +694,7 @@
   5.177    case JVM_CONSTANT_MethodHandleInError:
   5.178    case JVM_CONSTANT_MethodTypeInError:
   5.179      {
   5.180 -      Symbol* error = SystemDictionary::find_resolution_error(this_oop, index);
   5.181 -      guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
   5.182 -      ResourceMark rm;
   5.183 -      THROW_MSG_0(error, "");
   5.184 +      throw_resolution_error(this_oop, index, CHECK_NULL);
   5.185        break;
   5.186      }
   5.187  
   5.188 @@ -709,7 +718,8 @@
   5.189                                                                     THREAD);
   5.190        result_oop = value();
   5.191        if (HAS_PENDING_EXCEPTION) {
   5.192 -        save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
   5.193 +        MonitorLockerEx ml(this_oop->lock());  // lock cpool to change tag.
   5.194 +        save_and_throw_exception(this_oop, index, tag, CHECK_NULL);
   5.195        }
   5.196        break;
   5.197      }
   5.198 @@ -725,7 +735,8 @@
   5.199        Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD);
   5.200        result_oop = value();
   5.201        if (HAS_PENDING_EXCEPTION) {
   5.202 -        save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
   5.203 +        MonitorLockerEx ml(this_oop->lock());  // lock cpool to change tag.
   5.204 +        save_and_throw_exception(this_oop, index, tag, CHECK_NULL);
   5.205        }
   5.206        break;
   5.207      }
   5.208 @@ -756,7 +767,7 @@
   5.209  
   5.210    default:
   5.211      DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
   5.212 -                              this_oop(), index, cache_index, tag_value) );
   5.213 +                              this_oop(), index, cache_index, tag.value()));
   5.214      assert(false, "unexpected constant tag");
   5.215      break;
   5.216    }
     6.1 --- a/src/share/vm/oops/constantPool.hpp	Mon Mar 23 17:57:13 2020 +0000
     6.2 +++ b/src/share/vm/oops/constantPool.hpp	Mon May 05 19:53:00 2014 -0400
     6.3 @@ -823,9 +823,13 @@
     6.4    static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
     6.5  
     6.6    static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
     6.7 -  static void save_and_throw_exception(constantPoolHandle this_oop, int which, int tag_value, TRAPS);
     6.8    static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_oop, int index, TRAPS);
     6.9  
    6.10 +  // Exception handling
    6.11 +  static void throw_resolution_error(constantPoolHandle this_oop, int which, TRAPS);
    6.12 +  static Symbol* exception_message(constantPoolHandle this_oop, int which, constantTag tag, oop pending_exception);
    6.13 +  static void save_and_throw_exception(constantPoolHandle this_oop, int which, constantTag tag, TRAPS);
    6.14 +
    6.15   public:
    6.16    // Merging ConstantPool* support:
    6.17    bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
     7.1 --- a/src/share/vm/utilities/constantTag.cpp	Mon Mar 23 17:57:13 2020 +0000
     7.2 +++ b/src/share/vm/utilities/constantTag.cpp	Mon May 05 19:53:00 2014 -0400
     7.3 @@ -76,6 +76,20 @@
     7.4  }
     7.5  
     7.6  
     7.7 +jbyte constantTag::error_value() const {
     7.8 +  switch (_tag) {
     7.9 +  case JVM_CONSTANT_UnresolvedClass:
    7.10 +    return JVM_CONSTANT_UnresolvedClassInError;
    7.11 +  case JVM_CONSTANT_MethodHandle:
    7.12 +    return JVM_CONSTANT_MethodHandleInError;
    7.13 +  case JVM_CONSTANT_MethodType:
    7.14 +    return JVM_CONSTANT_MethodTypeInError;
    7.15 +  default:
    7.16 +    ShouldNotReachHere();
    7.17 +    return JVM_CONSTANT_Invalid;
    7.18 +  }
    7.19 +}
    7.20 +
    7.21  const char* constantTag::internal_name() const {
    7.22    switch (_tag) {
    7.23      case JVM_CONSTANT_Invalid :
     8.1 --- a/src/share/vm/utilities/constantTag.hpp	Mon Mar 23 17:57:13 2020 +0000
     8.2 +++ b/src/share/vm/utilities/constantTag.hpp	Mon May 05 19:53:00 2014 -0400
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -109,6 +109,7 @@
    8.11    }
    8.12  
    8.13    jbyte value() const                { return _tag; }
    8.14 +  jbyte error_value() const;
    8.15    jbyte non_error_value() const;
    8.16  
    8.17    BasicType basic_type() const;        // if used with ldc, what kind of value gets pushed?
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/runtime/ClassResolutionFail/Property.java	Mon May 05 19:53:00 2014 -0400
     9.3 @@ -0,0 +1,27 @@
     9.4 +/*
     9.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.
    9.11 + *
    9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.15 + * version 2 for more details (a copy is included in the LICENSE file that
    9.16 + * accompanied this code).
    9.17 + *
    9.18 + * You should have received a copy of the GNU General Public License version
    9.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.21 + *
    9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.23 + * or visit www.oracle.com if you need additional information or have any
    9.24 + * questions.
    9.25 + */
    9.26 +
    9.27 +// Class PropertySuper is not found.
    9.28 +
    9.29 +public class Property extends PropertySuper {
    9.30 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/runtime/ClassResolutionFail/PropertySuper.java	Mon May 05 19:53:00 2014 -0400
    10.3 @@ -0,0 +1,28 @@
    10.4 +/*
    10.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.
   10.11 + *
   10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.15 + * version 2 for more details (a copy is included in the LICENSE file that
   10.16 + * accompanied this code).
   10.17 + *
   10.18 + * You should have received a copy of the GNU General Public License version
   10.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.21 + *
   10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.23 + * or visit www.oracle.com if you need additional information or have any
   10.24 + * questions.
   10.25 + */
   10.26 +
   10.27 +// Class PropertySuper should be removed.
   10.28 +
   10.29 +public class PropertySuper {
   10.30 +  PropertySuper() { System.out.println("remove me for NoClassDefFoundError"); }
   10.31 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/runtime/ClassResolutionFail/TestClassResolutionFail.java	Mon May 05 19:53:00 2014 -0400
    11.3 @@ -0,0 +1,57 @@
    11.4 +/*
    11.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.
   11.11 + *
   11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.15 + * version 2 for more details (a copy is included in the LICENSE file that
   11.16 + * accompanied this code).
   11.17 + *
   11.18 + * You should have received a copy of the GNU General Public License version
   11.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.21 + *
   11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.23 + * or visit www.oracle.com if you need additional information or have any
   11.24 + * questions.
   11.25 + */
   11.26 +
   11.27 +/*
   11.28 + * @test TestClassResolutionFail
   11.29 + * @bug 8023697
   11.30 + * @summary This tests that failed class resolution doesn't report different class name in detail message for the first and subsequent times
   11.31 + */
   11.32 +
   11.33 +import java.io.File;
   11.34 +
   11.35 +public class TestClassResolutionFail {
   11.36 +    static String message;
   11.37 +    public static void test1() throws RuntimeException {
   11.38 +        try {
   11.39 +            Property p = new Property();
   11.40 +        } catch (LinkageError e) {
   11.41 +            message = e.getMessage();
   11.42 +        }
   11.43 +        try {
   11.44 +            Property p = new Property();
   11.45 +        } catch (LinkageError e) {
   11.46 +            System.out.println(e.getMessage());
   11.47 +            if (!e.getMessage().equals(message)) {
   11.48 +                throw new RuntimeException("Wrong message: " + message + " != " + e.getMessage());
   11.49 +            }
   11.50 +        }
   11.51 +    }
   11.52 +    public static void main(java.lang.String[] unused) throws Exception {
   11.53 +        // Remove PropertySuper class
   11.54 +        String testClasses = System.getProperty("test.classes", ".");
   11.55 +        File f = new File(testClasses + File.separator + "PropertySuper.class");
   11.56 +        f.delete();
   11.57 +        test1();
   11.58 +    }
   11.59 +}
   11.60 +

mercurial