8365858: FilteredJavaFieldStream is unnecessary

Reviewed-by: liach, jsjolen, coleenp, amenkov
This commit is contained in:
Paul Hübner 2025-09-16 19:17:53 +00:00 committed by Coleen Phillimore
parent e883dec6be
commit b75e35cb94
9 changed files with 28 additions and 185 deletions

View File

@ -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.
}

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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<InstanceKlass*>* 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()) {

View File

@ -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<FilteredField*> *FilteredFieldsMap::_filtered_fields =
new (mtServiceability) GrowableArray<FilteredField*>(3, mtServiceability);
void FilteredFieldsMap::initialize() {
int offset = reflect_ConstantPool::oop_offset();
_filtered_fields->append(new FilteredField(vmClasses::reflect_ConstantPool_klass(), offset));
}

View File

@ -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<mtInternal> {
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<FilteredField *> *_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

View File

@ -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);

View File

@ -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") ||