diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index e02820a2beb..c3f1fcac52f 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -2896,26 +2896,20 @@ JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ return JVMTI_ERROR_NONE; } - InstanceKlass* ik = InstanceKlass::cast(k); - int result_count = 0; - // First, count the fields. - FilteredFieldStream flds(ik, true, true); - result_count = flds.field_count(); + FilteredJavaFieldStream flds(ik); - // Allocate the result and fill it in - jfieldID* result_list = (jfieldID*) jvmtiMalloc(result_count * sizeof(jfieldID)); - // The JVMTI spec requires fields in the order they occur in the class file, - // this is the reverse order of what FieldStream hands out. - int id_index = (result_count - 1); + int result_count = flds.field_count(); - for (FilteredFieldStream src_st(ik, true, true); !src_st.eos(); src_st.next()) { - result_list[id_index--] = jfieldIDWorkaround::to_jfieldID( - ik, src_st.offset(), - src_st.access_flags().is_static()); + // Allocate the result and fill it in. + jfieldID* result_list = (jfieldID*)jvmtiMalloc(result_count * sizeof(jfieldID)); + for (int i = 0; i < result_count; i++, flds.next()) { + result_list[i] = jfieldIDWorkaround::to_jfieldID(ik, flds.offset(), + flds.access_flags().is_static()); } - assert(id_index == -1, "just checking"); + assert(flds.done(), "just checking"); + // Fill in the results *field_count_ptr = result_count; *fields_ptr = result_list; diff --git a/src/hotspot/share/runtime/reflectionUtils.hpp b/src/hotspot/share/runtime/reflectionUtils.hpp index 93bb541467a..5d43d27f660 100644 --- a/src/hotspot/share/runtime/reflectionUtils.hpp +++ b/src/hotspot/share/runtime/reflectionUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ #define SHARE_RUNTIME_REFLECTIONUTILS_HPP #include "memory/allStatic.hpp" +#include "oops/fieldStreams.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oopsHierarchy.hpp" @@ -237,4 +238,36 @@ class FilteredFieldStream : public FieldStream { } }; +// 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