diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index da093936ce5..60a63892518 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -79,7 +79,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/javaThread.hpp" #include "runtime/jniHandles.inline.hpp" -#include "runtime/reflectionUtils.hpp" +#include "runtime/reflection.hpp" #include "runtime/safepoint.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/threadSMR.hpp" @@ -3741,20 +3741,17 @@ oop java_lang_reflect_RecordComponent::create(InstanceKlass* holder, RecordCompo return element(); } -int reflect_ConstantPool::_oop_offset; - -#define CONSTANTPOOL_FIELDS_DO(macro) \ - macro(_oop_offset, k, "constantPoolOop", object_signature, false) +int reflect_ConstantPool::_vmholder_offset; void reflect_ConstantPool::compute_offsets() { InstanceKlass* k = vmClasses::reflect_ConstantPool_klass(); - // The field is called ConstantPool* in the sun.reflect.ConstantPool class. - CONSTANTPOOL_FIELDS_DO(FIELD_COMPUTE_OFFSET); + // The field is injected and called Object vmholder in the jdk.internal.reflect.ConstantPool class. + CONSTANTPOOL_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } #if INCLUDE_CDS void reflect_ConstantPool::serialize_offsets(SerializeClosure* f) { - CONSTANTPOOL_FIELDS_DO(FIELD_SERIALIZE_OFFSET); + CONSTANTPOOL_INJECTED_FIELDS(INJECTED_FIELD_SERIALIZE_OFFSET); } #endif @@ -3907,13 +3904,15 @@ Handle reflect_ConstantPool::create(TRAPS) { void reflect_ConstantPool::set_cp(oop reflect, ConstantPool* value) { + assert(_vmholder_offset != 0, "Uninitialized vmholder"); oop mirror = value->pool_holder()->java_mirror(); // Save the mirror to get back the constant pool. - reflect->obj_field_put(_oop_offset, mirror); + reflect->obj_field_put(_vmholder_offset, mirror); } ConstantPool* reflect_ConstantPool::get_cp(oop reflect) { - oop mirror = reflect->obj_field(_oop_offset); + assert(_vmholder_offset != 0, "Uninitialized vmholder"); + oop mirror = reflect->obj_field(_vmholder_offset); InstanceKlass* ik = java_lang_Class::as_InstanceKlass(mirror); // Get the constant pool back from the klass. Since class redefinition @@ -5554,5 +5553,4 @@ int InjectedField::compute_offset() { void javaClasses_init() { JavaClasses::compute_offsets(); JavaClasses::check_offsets(); - FilteredFieldsMap::initialize(); // must be done after computing offsets. } diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 6f82ca10fd6..b137f1a8035 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -936,12 +936,16 @@ class java_lang_Module { friend class JavaClasses; }; +#define CONSTANTPOOL_INJECTED_FIELDS(macro) \ + macro(reflect_ConstantPool, vmholder, object_signature, false) + // Interface to jdk.internal.reflect.ConstantPool objects class reflect_ConstantPool { private: // Note that to reduce dependencies on the JDK we compute these - // offsets at run-time. - static int _oop_offset; + // offsets at run-time. This field is the oop offset for the + // actual constant pool, previously called constantPoolOop. + static int _vmholder_offset; static void compute_offsets(); @@ -953,7 +957,6 @@ class reflect_ConstantPool { // Accessors static void set_cp(oop reflect, ConstantPool* value); - static int oop_offset() { CHECK_INIT(_oop_offset); } static ConstantPool* get_cp(oop reflect); diff --git a/src/hotspot/share/classfile/javaClassesImpl.hpp b/src/hotspot/share/classfile/javaClassesImpl.hpp index b450a4e3cc4..5f88f708523 100644 --- a/src/hotspot/share/classfile/javaClassesImpl.hpp +++ b/src/hotspot/share/classfile/javaClassesImpl.hpp @@ -42,7 +42,8 @@ THREAD_INJECTED_FIELDS(macro) \ VTHREAD_INJECTED_FIELDS(macro) \ INTERNALERROR_INJECTED_FIELDS(macro) \ - STACKCHUNK_INJECTED_FIELDS(macro) + STACKCHUNK_INJECTED_FIELDS(macro) \ + CONSTANTPOOL_INJECTED_FIELDS(macro) #define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \ klass::_##name##_offset = JavaClasses::compute_injected_offset(InjectedFieldID::klass##_##name##_enum); diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 3eb507ba5e3..5642cd9ff8f 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -38,6 +38,7 @@ #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/fieldStreams.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayOop.inline.hpp" @@ -68,7 +69,6 @@ #include "runtime/objectMonitor.inline.hpp" #include "runtime/os.hpp" #include "runtime/osThread.hpp" -#include "runtime/reflectionUtils.hpp" #include "runtime/signature.hpp" #include "runtime/threadHeapSampler.hpp" #include "runtime/threads.hpp" @@ -2841,9 +2841,9 @@ JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ InstanceKlass* ik = InstanceKlass::cast(k); - FilteredJavaFieldStream flds(ik); + JavaFieldStream flds(ik); - int result_count = flds.field_count(); + int result_count = ik->java_fields_count(); // Allocate the result and fill it in. jfieldID* result_list = (jfieldID*)jvmtiMalloc(result_count * sizeof(jfieldID)); diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index 4febb4f3125..a69c7cb7142 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -36,6 +36,7 @@ #include "oops/access.inline.hpp" #include "oops/arrayOop.hpp" #include "oops/constantPool.inline.hpp" +#include "oops/fieldStreams.inline.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" @@ -58,7 +59,6 @@ #include "runtime/jniHandles.inline.hpp" #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" -#include "runtime/reflectionUtils.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadSMR.hpp" #include "runtime/timerTrace.hpp" @@ -429,8 +429,8 @@ int ClassFieldMap::interfaces_field_count(InstanceKlass* ik) { const Array* interfaces = ik->transitive_interfaces(); int count = 0; for (int i = 0; i < interfaces->length(); i++) { - FilteredJavaFieldStream fld(interfaces->at(i)); - count += fld.field_count(); + count += interfaces->at(i)->java_fields_count(); + } return count; } @@ -452,11 +452,10 @@ ClassFieldMap* ClassFieldMap::create_map_of_static_fields(Klass* k) { // Need to calculate start index of this class fields: number of fields in all interfaces and superclasses. int index = interfaces_field_count(ik); for (InstanceKlass* super_klass = ik->super(); super_klass != nullptr; super_klass = super_klass->super()) { - FilteredJavaFieldStream super_fld(super_klass); - index += super_fld.field_count(); + index += super_klass->java_fields_count(); } - for (FilteredJavaFieldStream fld(ik); !fld.done(); fld.next(), index++) { + for (JavaFieldStream fld(ik); !fld.done(); fld.next(), index++) { // ignore instance fields if (!fld.access_flags().is_static()) { continue; @@ -479,13 +478,12 @@ ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) { // fields of the superclasses are reported first, so need to know total field number to calculate field indices int total_field_number = interfaces_field_count(ik); for (InstanceKlass* klass = ik; klass != nullptr; klass = klass->super()) { - FilteredJavaFieldStream fld(klass); - total_field_number += fld.field_count(); + total_field_number += klass->java_fields_count(); } for (InstanceKlass* klass = ik; klass != nullptr; klass = klass->super()) { - FilteredJavaFieldStream fld(klass); - int start_index = total_field_number - fld.field_count(); + JavaFieldStream fld(klass); + int start_index = total_field_number - klass->java_fields_count(); for (int index = 0; !fld.done(); fld.next(), index++) { // ignore static fields if (fld.access_flags().is_static()) { diff --git a/src/hotspot/share/runtime/reflectionUtils.cpp b/src/hotspot/share/runtime/reflectionUtils.cpp deleted file mode 100644 index ba1e167f1d6..00000000000 --- a/src/hotspot/share/runtime/reflectionUtils.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 1999, 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 "classfile/javaClasses.hpp" -#include "classfile/vmClasses.hpp" -#include "oops/instanceKlass.inline.hpp" -#include "runtime/reflectionUtils.hpp" - - -GrowableArray *FilteredFieldsMap::_filtered_fields = - new (mtServiceability) GrowableArray(3, mtServiceability); - - -void FilteredFieldsMap::initialize() { - int offset = reflect_ConstantPool::oop_offset(); - _filtered_fields->append(new FilteredField(vmClasses::reflect_ConstantPool_klass(), offset)); -} diff --git a/src/hotspot/share/runtime/reflectionUtils.hpp b/src/hotspot/share/runtime/reflectionUtils.hpp deleted file mode 100644 index 5753f46055e..00000000000 --- a/src/hotspot/share/runtime/reflectionUtils.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 1999, 2024, 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. - * - */ - -#ifndef SHARE_RUNTIME_REFLECTIONUTILS_HPP -#define SHARE_RUNTIME_REFLECTIONUTILS_HPP - -#include "memory/allStatic.hpp" -#include "oops/fieldStreams.inline.hpp" -#include "oops/instanceKlass.hpp" -#include "oops/oopsHierarchy.hpp" -#include "runtime/reflection.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/growableArray.hpp" - -class FilteredField : public CHeapObj { - private: - Klass* _klass; - int _field_offset; - - public: - FilteredField(Klass* klass, int field_offset) { - _klass = klass; - _field_offset = field_offset; - } - Klass* klass() { return _klass; } - int field_offset() { return _field_offset; } -}; - -class FilteredFieldsMap : AllStatic { - private: - static GrowableArray *_filtered_fields; - public: - static void initialize(); - static bool is_filtered_field(Klass* klass, int field_offset) { - for (int i=0; i < _filtered_fields->length(); i++) { - if (klass == _filtered_fields->at(i)->klass() && - field_offset == _filtered_fields->at(i)->field_offset()) { - return true; - } - } - return false; - } - static int filtered_fields_count(Klass* klass, bool local_only) { - int nflds = 0; - for (int i=0; i < _filtered_fields->length(); i++) { - if (local_only && klass == _filtered_fields->at(i)->klass()) { - nflds++; - } else if (klass->is_subtype_of(_filtered_fields->at(i)->klass())) { - nflds++; - } - } - return nflds; - } -}; - -// Iterate over Java fields filtering fields like reflection does. -class FilteredJavaFieldStream : public JavaFieldStream { -private: - InstanceKlass* _klass; - int _filtered_fields_count; - bool has_filtered_field() const { return (_filtered_fields_count > 0); } - void skip_filtered_fields() { - if (has_filtered_field()) { - while (!done() && FilteredFieldsMap::is_filtered_field((Klass*)_klass, offset())) { - JavaFieldStream::next(); - } - } - } - -public: - FilteredJavaFieldStream(InstanceKlass* klass) - : JavaFieldStream(klass), - _klass(klass), - _filtered_fields_count(FilteredFieldsMap::filtered_fields_count(klass, true)) - { - // skip filtered fields at the beginning - skip_filtered_fields(); - } - int field_count() const { - return _klass->java_fields_count() - _filtered_fields_count; - } - void next() { - JavaFieldStream::next(); - skip_filtered_fields(); - } -}; - -#endif // SHARE_RUNTIME_REFLECTIONUTILS_HPP diff --git a/src/java.base/share/classes/jdk/internal/reflect/ConstantPool.java b/src/java.base/share/classes/jdk/internal/reflect/ConstantPool.java index d56ecff5e36..be241a1eca5 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/ConstantPool.java +++ b/src/java.base/share/classes/jdk/internal/reflect/ConstantPool.java @@ -106,13 +106,6 @@ public class ConstantPool { // Internals only below this point // - static { - Reflection.registerFieldsToFilter(ConstantPool.class, Set.of("constantPoolOop")); - } - - // HotSpot-internal constant pool object (set by the VM, name known to the VM) - private Object constantPoolOop; - private native int getSize0 (); private native Class getClassAt0 (int index); private native Class getClassAtIfLoaded0 (int index); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 6501d082075..2ea54f2b4ef 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -949,9 +949,6 @@ public class TestResolvedJavaType extends TypeUniverse { * Replicates the semantics of jdk.internal.reflect.Reflection#fieldFilterMap. */ private static boolean isHiddenFromReflection(ResolvedJavaField f) { - if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(ConstantPool.class)) && f.getName().equals("constantPoolOop")) { - return true; - } if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Class.class))) { String name = f.getName(); return name.equals("classLoader") ||