/*
 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "cds/cdsConfig.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/verifier.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/linkResolver.hpp"
#include "jvm.h"
#include "logging/log.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
#include "runtime/vframe.inline.hpp"
#include "utilities/formatBuffer.hpp"

static void trace_class_resolution(oop mirror) {
  if (mirror == nullptr || java_lang_Class::is_primitive(mirror)) {
    return;
  }
  Klass* to_class = java_lang_Class::as_Klass(mirror);
  ResourceMark rm;
  int line_number = -1;
  const char * source_file = nullptr;
  Klass* caller = nullptr;
  JavaThread* jthread = JavaThread::current();
  if (jthread->has_last_Java_frame()) {
    vframeStream vfst(jthread);
    // skip over any frames belonging to java.lang.Class
    while (!vfst.at_end() &&
           vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class()) {
      vfst.next();
    }
    if (!vfst.at_end()) {
      // this frame is a likely suspect
      caller = vfst.method()->method_holder();
      line_number = vfst.method()->line_number_from_bci(vfst.bci());
      Symbol* s = vfst.method()->method_holder()->source_file_name();
      if (s != nullptr) {
        source_file = s->as_C_string();
      }
    }
  }
  if (caller != nullptr) {
    const char * from = caller->external_name();
    const char * to = to_class->external_name();
    // print in a single call to reduce interleaving between threads
    if (source_file != nullptr) {
      log_debug(class, resolve)("%s %s %s:%d (reflection)", from, to, source_file, line_number);
    } else {
      log_debug(class, resolve)("%s %s (reflection)", from, to);
    }
  }
}


oop Reflection::box(jvalue* value, BasicType type, TRAPS) {
  if (type == T_VOID) {
    return nullptr;
  }
  if (is_reference_type(type)) {
    // regular objects are not boxed
    return cast_to_oop(value->l);
  }
  oop result = java_lang_boxing_object::create(type, value, CHECK_NULL);
  if (result == nullptr) {
    THROW_(vmSymbols::java_lang_IllegalArgumentException(), result);
  }
  return result;
}


BasicType Reflection::unbox_for_primitive(oop box, jvalue* value, TRAPS) {
  if (box == nullptr) {
    THROW_(vmSymbols::java_lang_IllegalArgumentException(), T_ILLEGAL);
  }
  return java_lang_boxing_object::get_value(box, value);
}

BasicType Reflection::unbox_for_regular_object(oop box, jvalue* value) {
  // Note:  box is really the unboxed oop.  It might even be a Short, etc.!
  value->l = cast_from_oop<jobject>(box);
  return T_OBJECT;
}


void Reflection::widen(jvalue* value, BasicType current_type, BasicType wide_type, TRAPS) {
  assert(wide_type != current_type, "widen should not be called with identical types");
  switch (wide_type) {
    case T_BOOLEAN:
    case T_BYTE:
    case T_CHAR:
      break;  // fail
    case T_SHORT:
      switch (current_type) {
        case T_BYTE:
          value->s = (jshort) value->b;
          return;
        default:
          break;
      }
      break;  // fail
    case T_INT:
      switch (current_type) {
        case T_BYTE:
          value->i = (jint) value->b;
          return;
        case T_CHAR:
          value->i = (jint) value->c;
          return;
        case T_SHORT:
          value->i = (jint) value->s;
          return;
        default:
          break;
      }
      break;  // fail
    case T_LONG:
      switch (current_type) {
        case T_BYTE:
          value->j = (jlong) value->b;
          return;
        case T_CHAR:
          value->j = (jlong) value->c;
          return;
        case T_SHORT:
          value->j = (jlong) value->s;
          return;
        case T_INT:
          value->j = (jlong) value->i;
          return;
        default:
          break;
      }
      break;  // fail
    case T_FLOAT:
      switch (current_type) {
        case T_BYTE:
          value->f = (jfloat) value->b;
          return;
        case T_CHAR:
          value->f = (jfloat) value->c;
          return;
        case T_SHORT:
          value->f = (jfloat) value->s;
          return;
        case T_INT:
          value->f = (jfloat) value->i;
          return;
        case T_LONG:
          value->f = (jfloat) value->j;
          return;
        default:
          break;
      }
      break;  // fail
    case T_DOUBLE:
      switch (current_type) {
        case T_BYTE:
          value->d = (jdouble) value->b;
          return;
        case T_CHAR:
          value->d = (jdouble) value->c;
          return;
        case T_SHORT:
          value->d = (jdouble) value->s;
          return;
        case T_INT:
          value->d = (jdouble) value->i;
          return;
        case T_FLOAT:
          value->d = (jdouble) value->f;
          return;
        case T_LONG:
          value->d = (jdouble) value->j;
          return;
        default:
          break;
      }
      break;  // fail
    default:
      break;  // fail
  }
  THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}


BasicType Reflection::array_get(jvalue* value, arrayOop a, int index, TRAPS) {
  if (!a->is_within_bounds(index)) {
    THROW_(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), T_ILLEGAL);
  }
  if (a->is_objArray()) {
    value->l = cast_from_oop<jobject>(objArrayOop(a)->obj_at(index));
    return T_OBJECT;
  } else {
    assert(a->is_typeArray(), "just checking");
    BasicType type = TypeArrayKlass::cast(a->klass())->element_type();
    switch (type) {
      case T_BOOLEAN:
        value->z = typeArrayOop(a)->bool_at(index);
        break;
      case T_CHAR:
        value->c = typeArrayOop(a)->char_at(index);
        break;
      case T_FLOAT:
        value->f = typeArrayOop(a)->float_at(index);
        break;
      case T_DOUBLE:
        value->d = typeArrayOop(a)->double_at(index);
        break;
      case T_BYTE:
        value->b = typeArrayOop(a)->byte_at(index);
        break;
      case T_SHORT:
        value->s = typeArrayOop(a)->short_at(index);
        break;
      case T_INT:
        value->i = typeArrayOop(a)->int_at(index);
        break;
      case T_LONG:
        value->j = typeArrayOop(a)->long_at(index);
        break;
      default:
        return T_ILLEGAL;
    }
    return type;
  }
}


void Reflection::array_set(jvalue* value, arrayOop a, int index, BasicType value_type, TRAPS) {
  if (!a->is_within_bounds(index)) {
    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
  }
  if (a->is_objArray()) {
    if (value_type == T_OBJECT) {
      oop obj = cast_to_oop(value->l);
      if (obj != nullptr) {
        Klass* element_klass = ObjArrayKlass::cast(a->klass())->element_klass();
        if (!obj->is_a(element_klass)) {
          THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array element type mismatch");
        }
      }
      objArrayOop(a)->obj_at_put(index, obj);
    }
  } else {
    assert(a->is_typeArray(), "just checking");
    BasicType array_type = TypeArrayKlass::cast(a->klass())->element_type();
    if (array_type != value_type) {
      // The widen operation can potentially throw an exception, but cannot block,
      // so typeArrayOop a is safe if the call succeeds.
      widen(value, value_type, array_type, CHECK);
    }
    switch (array_type) {
      case T_BOOLEAN:
        typeArrayOop(a)->bool_at_put(index, value->z);
        break;
      case T_CHAR:
        typeArrayOop(a)->char_at_put(index, value->c);
        break;
      case T_FLOAT:
        typeArrayOop(a)->float_at_put(index, value->f);
        break;
      case T_DOUBLE:
        typeArrayOop(a)->double_at_put(index, value->d);
        break;
      case T_BYTE:
        typeArrayOop(a)->byte_at_put(index, value->b);
        break;
      case T_SHORT:
        typeArrayOop(a)->short_at_put(index, value->s);
        break;
      case T_INT:
        typeArrayOop(a)->int_at_put(index, value->i);
        break;
      case T_LONG:
        typeArrayOop(a)->long_at_put(index, value->j);
        break;
      default:
        THROW(vmSymbols::java_lang_IllegalArgumentException());
    }
  }
}

static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) {
  assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
  BasicType type = java_lang_Class::primitive_type(basic_type_mirror);
  if (type == T_VOID) {
    THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
  }
  else {
    return Universe::typeArrayKlass(type);
  }
}

arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
  if (element_mirror == nullptr) {
    THROW_NULL(vmSymbols::java_lang_NullPointerException());
  }
  if (length < 0) {
    THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length));
  }
  if (java_lang_Class::is_primitive(element_mirror)) {
    Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
    return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
  } else {
    Klass* k = java_lang_Class::as_Klass(element_mirror);
    if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
      THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
    }
    return oopFactory::new_objArray(k, length, THREAD);
  }
}


arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop dim_array, TRAPS) {
  assert(dim_array->is_typeArray(), "just checking");
  assert(TypeArrayKlass::cast(dim_array->klass())->element_type() == T_INT, "just checking");

  if (element_mirror == nullptr) {
    THROW_NULL(vmSymbols::java_lang_NullPointerException());
  }

  int len = dim_array->length();
  if (len <= 0 || len > MAX_DIM) {
    THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
  }

  jint dimensions[MAX_DIM];   // C array copy of intArrayOop
  for (int i = 0; i < len; i++) {
    int d = dim_array->int_at(i);
    if (d < 0) {
      THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", d));
    }
    dimensions[i] = d;
  }

  Klass* klass;
  int dim = len;
  if (java_lang_Class::is_primitive(element_mirror)) {
    klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
  } else {
    klass = java_lang_Class::as_Klass(element_mirror);
    if (klass->is_array_klass()) {
      int k_dim = ArrayKlass::cast(klass)->dimension();
      if (k_dim + len > MAX_DIM) {
        THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
      }
      dim += k_dim;
    }
  }
  klass = klass->array_klass(dim, CHECK_NULL);
  oop obj = ArrayKlass::cast(klass)->multi_allocate(len, dimensions, CHECK_NULL);
  assert(obj->is_array(), "just checking");
  return arrayOop(obj);
}


static bool can_relax_access_check_for(const Klass* accessor,
                                       const Klass* accessee,
                                       bool classloader_only) {

  const InstanceKlass* accessor_ik = InstanceKlass::cast(accessor);
  const InstanceKlass* accessee_ik = InstanceKlass::cast(accessee);

  if (RelaxAccessControlCheck &&
    accessor_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION &&
    accessee_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION) {
    return classloader_only &&
      Verifier::relax_access_for(accessor_ik->class_loader()) &&
      accessor_ik->protection_domain() == accessee_ik->protection_domain() &&
      accessor_ik->class_loader() == accessee_ik->class_loader();
  }

  return false;
}

/*
    Type Accessibility check for public types: Callee Type T is accessible to Caller Type S if:

                        Callee T in             Callee T in package PT,
                        unnamed module          runtime module MT
 ------------------------------------------------------------------------------------------------

 Caller S in package     If MS is loose: YES      If same classloader/package (PS == PT): YES
 PS, runtime module MS   If MS can read T's       If same runtime module: (MS == MT): YES
                         unnamed module: YES
                                                  Else if (MS can read MT (establish readability) &&
                                                    ((MT exports PT to MS or to all modules) ||
                                                     (MT is open))): YES

 ------------------------------------------------------------------------------------------------
 Caller S in unnamed         YES                  Readability exists because unnamed module
 module UM                                            "reads" all modules
                                                  if (MT exports PT to UM or to all modules): YES

 ------------------------------------------------------------------------------------------------

 Note: a loose module is a module that can read all current and future unnamed modules.
*/
Reflection::VerifyClassAccessResults Reflection::verify_class_access(
  const Klass* current_class, const InstanceKlass* new_class, bool classloader_only) {

  // Verify that current_class can access new_class.  If the classloader_only
  // flag is set, we automatically allow any accesses in which current_class
  // doesn't have a classloader.
  if ((current_class == nullptr) ||
      (current_class == new_class) ||
      is_same_class_package(current_class, new_class)) {
    return ACCESS_OK;
  }

  // module boundaries
  if (new_class->is_public()) {
    // Find the module entry for current_class, the accessor
    ModuleEntry* module_from = current_class->module();
    // Find the module entry for new_class, the accessee
    ModuleEntry* module_to = new_class->module();

    // both in same (possibly unnamed) module
    if (module_from == module_to) {
      return ACCESS_OK;
    }

    // Acceptable access to a type in an unnamed module. Note that since
    // unnamed modules can read all unnamed modules, this also handles the
    // case where module_from is also unnamed but in a different class loader.
    if (!module_to->is_named() &&
        (module_from->can_read_all_unnamed() || module_from->can_read(module_to))) {
      return ACCESS_OK;
    }

    // Establish readability, check if module_from is allowed to read module_to.
    if (!module_from->can_read(module_to)) {
      return MODULE_NOT_READABLE;
    }

    // Access is allowed if module_to is open, i.e. all its packages are unqualifiedly exported
    if (module_to->is_open()) {
      return ACCESS_OK;
    }

    PackageEntry* package_to = new_class->package();
    assert(package_to != nullptr, "can not obtain new_class' package");

    {
      MutexLocker m1(Module_lock);

      // Once readability is established, if module_to exports T unqualifiedly,
      // (to all modules), than whether module_from is in the unnamed module
      // or not does not matter, access is allowed.
      if (package_to->is_unqual_exported()) {
        return ACCESS_OK;
      }

      // Access is allowed if both 1 & 2 hold:
      //   1. Readability, module_from can read module_to (established above).
      //   2. Either module_to exports T to module_from qualifiedly.
      //      or
      //      module_to exports T to all unnamed modules and module_from is unnamed.
      //      or
      //      module_to exports T unqualifiedly to all modules (checked above).
      if (!package_to->is_qexported_to(module_from)) {
        return TYPE_NOT_EXPORTED;
      }
    }
    return ACCESS_OK;
  }

  if (can_relax_access_check_for(current_class, new_class, classloader_only)) {
    return ACCESS_OK;
  }
  return OTHER_PROBLEM;
}

// Return an error message specific to the specified Klass*'s and result.
// This function must be called from within a block containing a ResourceMark.
char* Reflection::verify_class_access_msg(const Klass* current_class,
                                          const InstanceKlass* new_class,
                                          const VerifyClassAccessResults result) {
  assert(result != ACCESS_OK, "must be failure result");
  char * msg = nullptr;
  if (result != OTHER_PROBLEM && new_class != nullptr && current_class != nullptr) {
    // Find the module entry for current_class, the accessor
    ModuleEntry* module_from = current_class->module();
    const char * module_from_name = module_from->is_named() ? module_from->name()->as_C_string() : UNNAMED_MODULE;
    const char * current_class_name = current_class->external_name();

    // Find the module entry for new_class, the accessee
    ModuleEntry* module_to = nullptr;
    module_to = new_class->module();
    const char * module_to_name = module_to->is_named() ? module_to->name()->as_C_string() : UNNAMED_MODULE;
    const char * new_class_name = new_class->external_name();

    if (result == MODULE_NOT_READABLE) {
      assert(module_from->is_named(), "Unnamed modules can read all modules");
      if (module_to->is_named()) {
        size_t len = 100 + strlen(current_class_name) + 2*strlen(module_from_name) +
          strlen(new_class_name) + 2*strlen(module_to_name);
        msg = NEW_RESOURCE_ARRAY(char, len);
        jio_snprintf(msg, len - 1,
          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not read module %s",
          current_class_name, module_from_name, new_class_name,
          module_to_name, module_from_name, module_to_name);
      } else {
        oop jlm = module_to->module();
        assert(jlm != nullptr, "Null jlm in module_to ModuleEntry");
        intptr_t identity_hash = jlm->identity_hash();
        size_t len = 160 + strlen(current_class_name) + 2*strlen(module_from_name) +
          strlen(new_class_name) + 2*sizeof(uintx);
        msg = NEW_RESOURCE_ARRAY(char, len);
        jio_snprintf(msg, len - 1,
          "class %s (in module %s) cannot access class %s (in unnamed module @0x%zx) because module %s does not read unnamed module @0x%zx",
          current_class_name, module_from_name, new_class_name, uintx(identity_hash),
          module_from_name, uintx(identity_hash));
      }

    } else if (result == TYPE_NOT_EXPORTED) {
      assert(new_class->package() != nullptr,
             "Unnamed packages are always exported");
      const char * package_name =
        new_class->package()->name()->as_klass_external_name();
      assert(module_to->is_named(), "Unnamed modules export all packages");
      if (module_from->is_named()) {
        size_t len = 118 + strlen(current_class_name) + 2*strlen(module_from_name) +
          strlen(new_class_name) + 2*strlen(module_to_name) + strlen(package_name);
        msg = NEW_RESOURCE_ARRAY(char, len);
        jio_snprintf(msg, len - 1,
          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not export %s to module %s",
          current_class_name, module_from_name, new_class_name,
          module_to_name, module_to_name, package_name, module_from_name);
      } else {
        oop jlm = module_from->module();
        assert(jlm != nullptr, "Null jlm in module_from ModuleEntry");
        intptr_t identity_hash = jlm->identity_hash();
        size_t len = 170 + strlen(current_class_name) + strlen(new_class_name) +
          2*strlen(module_to_name) + strlen(package_name) + 2*sizeof(uintx);
        msg = NEW_RESOURCE_ARRAY(char, len);
        jio_snprintf(msg, len - 1,
          "class %s (in unnamed module @0x%zx) cannot access class %s (in module %s) because module %s does not export %s to unnamed module @0x%zx",
          current_class_name, uintx(identity_hash), new_class_name, module_to_name,
          module_to_name, package_name, uintx(identity_hash));
      }
    } else {
        ShouldNotReachHere();
    }
  }  // result != OTHER_PROBLEM...
  return msg;
}

bool Reflection::verify_member_access(const Klass* current_class,
                                      const Klass* resolved_class,
                                      const Klass* member_class,
                                      AccessFlags access,
                                      bool classloader_only,
                                      bool protected_restriction,
                                      TRAPS) {
  // Verify that current_class can access a member of member_class, where that
  // field's access bits are "access".  We assume that we've already verified
  // that current_class can access member_class.
  //
  // If the classloader_only flag is set, we automatically allow any accesses
  // in which current_class doesn't have a classloader.
  //
  // "resolved_class" is the runtime type of "member_class". Sometimes we don't
  // need this distinction (e.g. if all we have is the runtime type, or during
  // class file parsing when we only care about the static type); in that case
  // callers should ensure that resolved_class == member_class.
  //
  if ((current_class == nullptr) ||
      (current_class == member_class) ||
      access.is_public()) {
    return true;
  }

  if (current_class == member_class) {
    return true;
  }

  if (access.is_protected()) {
    if (!protected_restriction) {
      // See if current_class (or outermost host class) is a subclass of member_class
      // An interface may not access protected members of j.l.Object
      if (!current_class->is_interface() && current_class->is_subclass_of(member_class)) {
        if (access.is_static() || // static fields are ok, see 6622385
            current_class == resolved_class ||
            member_class == resolved_class ||
            current_class->is_subclass_of(resolved_class) ||
            resolved_class->is_subclass_of(current_class)) {
          return true;
        }
      }
    }
  }

  // package access
  if (!access.is_private() && is_same_class_package(current_class, member_class)) {
    return true;
  }

  // private access between different classes needs a nestmate check.
  if (access.is_private()) {
    if (current_class->is_instance_klass() && member_class->is_instance_klass() ) {
      InstanceKlass* cur_ik = const_cast<InstanceKlass*>(InstanceKlass::cast(current_class));
      InstanceKlass* field_ik = const_cast<InstanceKlass*>(InstanceKlass::cast(member_class));
      // Nestmate access checks may require resolution and validation of the nest-host.
      // It is up to the caller to check for pending exceptions and handle appropriately.
      bool access = cur_ik->has_nestmate_access_to(field_ik, CHECK_false);
      if (access) {
        guarantee(resolved_class->is_subclass_of(member_class), "must be!");
        return true;
      }
    }
  }

  // Check for special relaxations
  return can_relax_access_check_for(current_class, member_class, classloader_only);
}

bool Reflection::is_same_class_package(const Klass* class1, const Klass* class2) {
  return InstanceKlass::cast(class1)->is_same_class_package(class2);
}

// Checks that the 'outer' klass has declared 'inner' as being an inner klass. If not,
// throw an incompatible class change exception
// If inner_is_member, require the inner to be a member of the outer.
// If !inner_is_member, require the inner to be hidden (non-member).
// Caller is responsible for figuring out in advance which case must be true.
void Reflection::check_for_inner_class(const InstanceKlass* outer, const InstanceKlass* inner,
                                       bool inner_is_member, TRAPS) {
  InnerClassesIterator iter(outer);
  constantPoolHandle cp   (THREAD, outer->constants());
  for (; !iter.done(); iter.next()) {
    int ioff = iter.inner_class_info_index();
    int ooff = iter.outer_class_info_index();

    if (inner_is_member && ioff != 0 && ooff != 0) {
      if (cp->klass_name_at_matches(outer, ooff) &&
          cp->klass_name_at_matches(inner, ioff)) {
        Klass* o = cp->klass_at(ooff, CHECK);
        if (o == outer) {
          Klass* i = cp->klass_at(ioff, CHECK);
          if (i == inner) {
            return;
          }
        }
      }
    }

    if (!inner_is_member && ioff != 0 && ooff == 0 &&
        cp->klass_name_at_matches(inner, ioff)) {
      Klass* i = cp->klass_at(ioff, CHECK);
      if (i == inner) {
        return;
      }
    }
  }

  // 'inner' not declared as an inner klass in outer
  ResourceMark rm(THREAD);
  // Names are all known to be < 64k so we know this formatted message is not excessively large.
  Exceptions::fthrow(
    THREAD_AND_LOCATION,
    vmSymbols::java_lang_IncompatibleClassChangeError(),
    "%s and %s disagree on InnerClasses attribute",
    outer->external_name(),
    inner->external_name()
  );
}

static objArrayHandle get_parameter_types(const methodHandle& method,
                                          int parameter_count,
                                          oop* return_type,
                                          TRAPS) {
  objArrayOop m;
  if (parameter_count == 0) {
    // Avoid allocating an array for the empty case
    // Still need to parse the signature for the return type below
    m = Universe::the_empty_class_array();
  } else {
    // Allocate array holding parameter types (java.lang.Class instances)
    m = oopFactory::new_objArray(vmClasses::Class_klass(), parameter_count, CHECK_(objArrayHandle()));
  }
  objArrayHandle mirrors(THREAD, m);
  int index = 0;
  // Collect parameter types
  ResourceMark rm(THREAD);
  for (ResolvingSignatureStream ss(method()); !ss.is_done(); ss.next()) {
    oop mirror = ss.as_java_mirror(SignatureStream::NCDFError, CHECK_(objArrayHandle()));
    if (log_is_enabled(Debug, class, resolve)) {
      trace_class_resolution(mirror);
    }
    if (!ss.at_return_type()) {
      mirrors->obj_at_put(index++, mirror);
    } else if (return_type != nullptr) {
      // Collect return type as well
      assert(ss.at_return_type(), "return type should be present");
      *return_type = mirror;
    }
  }
  assert(index == parameter_count, "invalid parameter count");
  return mirrors;
}

static objArrayHandle get_exception_types(const methodHandle& method, TRAPS) {
  return method->resolved_checked_exceptions(THREAD);
}

static Handle new_type(Symbol* signature, Klass* k, TRAPS) {
  ResolvingSignatureStream ss(signature, k, false);
  oop nt = ss.as_java_mirror(SignatureStream::NCDFError, CHECK_NH);
  if (log_is_enabled(Debug, class, resolve)) {
    trace_class_resolution(nt);
  }
  return Handle(THREAD, nt);
}

oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS) {
  // Allow jdk.internal.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods.
  assert(!method()->is_object_initializer() &&
         (for_constant_pool_access || !method()->is_static_initializer()),
         "Should not be the initializer");
  InstanceKlass* holder = method->method_holder();
  int slot = method->method_idnum();

  Symbol*  signature  = method->signature();
  int parameter_count = ArgumentCount(signature).size();
  oop return_type_oop = nullptr;
  objArrayHandle parameter_types = get_parameter_types(method, parameter_count, &return_type_oop, CHECK_NULL);
  if (parameter_types.is_null() || return_type_oop == nullptr) return nullptr;

  Handle return_type(THREAD, return_type_oop);

  objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
  assert(!exception_types.is_null(), "cannot return null");

  Symbol*  method_name = method->name();
  oop name_oop = StringTable::intern(method_name, CHECK_NULL);
  Handle name = Handle(THREAD, name_oop);
  if (name == nullptr) return nullptr;

  const int modifiers = method->access_flags().as_method_flags();

  Handle mh = java_lang_reflect_Method::create(CHECK_NULL);

  java_lang_reflect_Method::set_clazz(mh(), holder->java_mirror());
  java_lang_reflect_Method::set_slot(mh(), slot);
  java_lang_reflect_Method::set_name(mh(), name());
  java_lang_reflect_Method::set_return_type(mh(), return_type());
  java_lang_reflect_Method::set_parameter_types(mh(), parameter_types());
  java_lang_reflect_Method::set_exception_types(mh(), exception_types());
  java_lang_reflect_Method::set_modifiers(mh(), modifiers);
  java_lang_reflect_Method::set_override(mh(), false);
  if (method->generic_signature() != nullptr) {
    Symbol*  gs = method->generic_signature();
    Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
    java_lang_reflect_Method::set_signature(mh(), sig());
  }
  typeArrayOop an_oop = Annotations::make_java_array(method->annotations(), CHECK_NULL);
  java_lang_reflect_Method::set_annotations(mh(), an_oop);
  an_oop = Annotations::make_java_array(method->parameter_annotations(), CHECK_NULL);
  java_lang_reflect_Method::set_parameter_annotations(mh(), an_oop);
  an_oop = Annotations::make_java_array(method->annotation_default(), CHECK_NULL);
  java_lang_reflect_Method::set_annotation_default(mh(), an_oop);
  return mh();
}


oop Reflection::new_constructor(const methodHandle& method, TRAPS) {
  assert(method()->is_object_initializer(), "Should be the initializer");

  InstanceKlass* holder = method->method_holder();
  int slot = method->method_idnum();

  Symbol*  signature  = method->signature();
  int parameter_count = ArgumentCount(signature).size();
  objArrayHandle parameter_types = get_parameter_types(method, parameter_count, nullptr, CHECK_NULL);
  if (parameter_types.is_null()) return nullptr;

  objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
  assert(!exception_types.is_null(), "cannot return null");

  const int modifiers = method->access_flags().as_method_flags();

  Handle ch = java_lang_reflect_Constructor::create(CHECK_NULL);

  java_lang_reflect_Constructor::set_clazz(ch(), holder->java_mirror());
  java_lang_reflect_Constructor::set_slot(ch(), slot);
  java_lang_reflect_Constructor::set_parameter_types(ch(), parameter_types());
  java_lang_reflect_Constructor::set_exception_types(ch(), exception_types());
  java_lang_reflect_Constructor::set_modifiers(ch(), modifiers);
  java_lang_reflect_Constructor::set_override(ch(), false);
  if (method->generic_signature() != nullptr) {
    Symbol*  gs = method->generic_signature();
    Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
    java_lang_reflect_Constructor::set_signature(ch(), sig());
  }
  typeArrayOop an_oop = Annotations::make_java_array(method->annotations(), CHECK_NULL);
  java_lang_reflect_Constructor::set_annotations(ch(), an_oop);
  an_oop = Annotations::make_java_array(method->parameter_annotations(), CHECK_NULL);
  java_lang_reflect_Constructor::set_parameter_annotations(ch(), an_oop);
  return ch();
}


oop Reflection::new_field(fieldDescriptor* fd, TRAPS) {
  Symbol*  field_name = fd->name();
  oop name_oop = StringTable::intern(field_name, CHECK_NULL);
  Handle name = Handle(THREAD, name_oop);
  Symbol*  signature  = fd->signature();
  InstanceKlass* holder = fd->field_holder();
  Handle type = new_type(signature, holder, CHECK_NULL);
  Handle rh  = java_lang_reflect_Field::create(CHECK_NULL);

  java_lang_reflect_Field::set_clazz(rh(), fd->field_holder()->java_mirror());
  java_lang_reflect_Field::set_slot(rh(), fd->index());
  java_lang_reflect_Field::set_name(rh(), name());
  java_lang_reflect_Field::set_type(rh(), type());
  if (fd->is_trusted_final()) {
    java_lang_reflect_Field::set_trusted_final(rh());
  }
  // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here.
  java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_field_flags());
  java_lang_reflect_Field::set_override(rh(), false);
  if (fd->has_generic_signature()) {
    Symbol*  gs = fd->generic_signature();
    Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
    java_lang_reflect_Field::set_signature(rh(), sig());
  }
  typeArrayOop an_oop = Annotations::make_java_array(fd->annotations(), CHECK_NULL);
  java_lang_reflect_Field::set_annotations(rh(), an_oop);
  return rh();
}

oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
                              int flags, TRAPS) {

  Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);

  if(nullptr != sym) {
    Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
    java_lang_reflect_Parameter::set_name(rh(), name());
  } else {
    java_lang_reflect_Parameter::set_name(rh(), nullptr);
  }

  java_lang_reflect_Parameter::set_modifiers(rh(), flags);
  java_lang_reflect_Parameter::set_executable(rh(), method());
  java_lang_reflect_Parameter::set_index(rh(), index);
  return rh();
}


static methodHandle resolve_interface_call(InstanceKlass* klass,
                                           const methodHandle& method,
                                           Klass* recv_klass,
                                           Handle receiver,
                                           TRAPS) {

  assert(!method.is_null() , "method should not be null");

  CallInfo info;
  Symbol*  signature  = method->signature();
  Symbol*  name       = method->name();
  LinkResolver::resolve_interface_call(info, receiver, recv_klass,
                                       LinkInfo(klass, name, signature),
                                       true,
                                       CHECK_(methodHandle()));
  return methodHandle(THREAD, info.selected_method());
}

// Conversion
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror) {
  assert(java_lang_Class::is_primitive(basic_type_mirror),
    "just checking");
  return java_lang_Class::primitive_type(basic_type_mirror);
}

// Narrowing of basic types. Used to create correct jvalues for
// boolean, byte, char and short return return values from interpreter
// which are returned as ints. Throws IllegalArgumentException.
static void narrow(jvalue* value, BasicType narrow_type, TRAPS) {
  switch (narrow_type) {
  case T_BOOLEAN:
    value->z = (jboolean) (value->i & 1);
    return;
  case T_BYTE:
    value->b = (jbyte)value->i;
    return;
  case T_CHAR:
    value->c = (jchar)value->i;
    return;
  case T_SHORT:
    value->s = (jshort)value->i;
    return;
  default:
    break; // fail
  }
  THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}


// Method call (shared by invoke_method and invoke_constructor)
static oop invoke(InstanceKlass* klass,
                  const methodHandle& reflected_method,
                  Handle receiver,
                  bool override,
                  objArrayHandle ptypes,
                  BasicType rtype,
                  objArrayHandle args,
                  bool is_method_invoke,
                  TRAPS) {

  ResourceMark rm(THREAD);

  methodHandle method;      // actual method to invoke
  Klass* target_klass;      // target klass, receiver's klass for non-static

  // Ensure klass is initialized
  klass->initialize(CHECK_NULL);

  bool is_static = reflected_method->is_static();
  if (is_static) {
    // ignore receiver argument
    method = reflected_method;
    target_klass = klass;
  } else {
    // check for null receiver
    if (receiver.is_null()) {
      THROW_NULL(vmSymbols::java_lang_NullPointerException());
    }
    // Check class of receiver against class declaring method
    if (!receiver->is_a(klass)) {
      THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class");
    }
    // target klass is receiver's klass
    target_klass = receiver->klass();
    // no need to resolve if method is private or <init>
    if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) {
      method = reflected_method;
    } else {
      // resolve based on the receiver
      if (reflected_method->method_holder()->is_interface()) {
        // resolve interface call
        //
        // Match resolution errors with those thrown due to reflection inlining
        // Linktime resolution & IllegalAccessCheck already done by Class.getMethod()
        method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD);
        if (HAS_PENDING_EXCEPTION) {
          // Method resolution threw an exception; wrap it in an InvocationTargetException
          oop resolution_exception = PENDING_EXCEPTION;
          CLEAR_PENDING_EXCEPTION;
          // JVMTI has already reported the pending exception
          // JVMTI internal flag reset is needed in order to report InvocationTargetException
          JvmtiExport::clear_detected_exception(THREAD);
          JavaCallArguments args(Handle(THREAD, resolution_exception));
          THROW_ARG_NULL(vmSymbols::java_lang_reflect_InvocationTargetException(),
                         vmSymbols::throwable_void_signature(),
                         &args);
        }
      }  else {
        // if the method can be overridden, we resolve using the vtable index.
        assert(!reflected_method->has_itable_index(), "");
        int index = reflected_method->vtable_index();
        method = reflected_method;
        if (index != Method::nonvirtual_vtable_index) {
          method = methodHandle(THREAD, target_klass->method_at_vtable(index));
        }
        if (!method.is_null()) {
          // Check for abstract methods as well
          if (method->is_abstract()) {
            // new default: 6531596
            ResourceMark rm(THREAD);
            stringStream ss;
            ss.print("'");
            Method::print_external_name(&ss, target_klass, method->name(), method->signature());
            ss.print("'");
            Handle h_origexception = Exceptions::new_exception(THREAD,
              vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
            JavaCallArguments args(h_origexception);
            THROW_ARG_NULL(vmSymbols::java_lang_reflect_InvocationTargetException(),
                           vmSymbols::throwable_void_signature(),
                           &args);
          }
        }
      }
    }
  }

  // I believe this is a ShouldNotGetHere case which requires
  // an internal vtable bug. If you ever get this please let Karen know.
  if (method.is_null()) {
    ResourceMark rm(THREAD);
    stringStream ss;
    ss.print("'");
    Method::print_external_name(&ss, klass,
                                     reflected_method->name(),
                                     reflected_method->signature());
    ss.print("'");
    THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string());
  }

  assert(ptypes->is_objArray(), "just checking");
  int args_len = args.is_null() ? 0 : args->length();
  // Check number of arguments
  if (ptypes->length() != args_len) {
    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
                   "wrong number of arguments");
  }

  // Create object to contain parameters for the JavaCall
  JavaCallArguments java_args(method->size_of_parameters());

  if (!is_static) {
    java_args.push_oop(receiver);
  }

  for (int i = 0; i < args_len; i++) {
    oop type_mirror = ptypes->obj_at(i);
    oop arg = args->obj_at(i);
    if (java_lang_Class::is_primitive(type_mirror)) {
      jvalue value;
      BasicType ptype = basic_type_mirror_to_basic_type(type_mirror);
      BasicType atype = Reflection::unbox_for_primitive(arg, &value, CHECK_NULL);
      if (ptype != atype) {
        Reflection::widen(&value, atype, ptype, CHECK_NULL);
      }
      switch (ptype) {
        case T_BOOLEAN:     java_args.push_int(value.z);    break;
        case T_CHAR:        java_args.push_int(value.c);    break;
        case T_BYTE:        java_args.push_int(value.b);    break;
        case T_SHORT:       java_args.push_int(value.s);    break;
        case T_INT:         java_args.push_int(value.i);    break;
        case T_LONG:        java_args.push_long(value.j);   break;
        case T_FLOAT:       java_args.push_float(value.f);  break;
        case T_DOUBLE:      java_args.push_double(value.d); break;
        default:
          THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
      }
    } else {
      if (arg != nullptr) {
        Klass* k = java_lang_Class::as_Klass(type_mirror);
        if (!arg->is_a(k)) {
          THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
                         "argument type mismatch");
        }
      }
      Handle arg_handle(THREAD, arg);         // Create handle for argument
      java_args.push_oop(arg_handle); // Push handle
    }
  }

  assert(java_args.size_of_parameters() == method->size_of_parameters(),
    "just checking");

  // All oops (including receiver) is passed in as Handles. An potential oop is returned as an
  // oop (i.e., NOT as an handle)
  JavaValue result(rtype);
  JavaCalls::call(&result, method, &java_args, THREAD);

  if (HAS_PENDING_EXCEPTION) {
    // Method threw an exception; wrap it in an InvocationTargetException
    oop target_exception = PENDING_EXCEPTION;
    CLEAR_PENDING_EXCEPTION;
    // JVMTI has already reported the pending exception
    // JVMTI internal flag reset is needed in order to report InvocationTargetException
    JvmtiExport::clear_detected_exception(THREAD);

    JavaCallArguments args(Handle(THREAD, target_exception));
    THROW_ARG_NULL(vmSymbols::java_lang_reflect_InvocationTargetException(),
                   vmSymbols::throwable_void_signature(),
                   &args);
  } else {
    if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) {
      narrow((jvalue*)result.get_value_addr(), rtype, CHECK_NULL);
    }
    return Reflection::box((jvalue*)result.get_value_addr(), rtype, THREAD);
  }
}

// This would be nicer if, say, java.lang.reflect.Method was a subclass
// of java.lang.reflect.Constructor

oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS) {
  oop mirror             = java_lang_reflect_Method::clazz(method_mirror);
  int slot               = java_lang_reflect_Method::slot(method_mirror);
  bool override          = java_lang_reflect_Method::override(method_mirror) != 0;
  objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Method::parameter_types(method_mirror)));

  oop return_type_mirror = java_lang_reflect_Method::return_type(method_mirror);
  BasicType rtype;
  if (java_lang_Class::is_primitive(return_type_mirror)) {
    rtype = basic_type_mirror_to_basic_type(return_type_mirror);
  } else {
    rtype = T_OBJECT;
  }

  InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
  Method* m = klass->method_with_idnum(slot);
  if (m == nullptr) {
    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "invoke");
  }
  methodHandle method(THREAD, m);

  return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD);
}


oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, TRAPS) {
  oop mirror             = java_lang_reflect_Constructor::clazz(constructor_mirror);
  int slot               = java_lang_reflect_Constructor::slot(constructor_mirror);
  bool override          = java_lang_reflect_Constructor::override(constructor_mirror) != 0;
  objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror)));

  InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
  Method* m = klass->method_with_idnum(slot);
  if (m == nullptr) {
    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "invoke");
  }
  methodHandle method(THREAD, m);
  assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor");

  // Make sure klass gets initialize
  klass->initialize(CHECK_NULL);

  // Create new instance (the receiver)
  klass->check_valid_for_instantiation(false, CHECK_NULL);
  Handle receiver = klass->allocate_instance_handle(CHECK_NULL);

  // Ignore result from call and return receiver
  invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL);
  return receiver();
}
