8318563: GetClassFields should not use random access to field

Reviewed-by: sspitsyn, cjplummer, fparain
This commit is contained in:
Alex Menkov 2024-01-12 20:41:49 +00:00
parent 9e9c05f0ee
commit 84cf4cb350
2 changed files with 44 additions and 17 deletions

View File

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

View File

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