8318626: GetClassFields does not filter out ConstantPool.constantPoolOop field

Reviewed-by: sspitsyn, lmesnik
This commit is contained in:
Alex Menkov 2023-11-29 20:10:27 +00:00
parent ea6e92ed0d
commit d1e73b1299
3 changed files with 150 additions and 5 deletions
src/hotspot/share/runtime
test/hotspot/jtreg/serviceability/jvmti/GetClassFields/FilteredFields

@ -214,20 +214,26 @@ class FilteredFieldStream : public FieldStream {
private:
int _filtered_fields_count;
bool has_filtered_field() { return (_filtered_fields_count > 0); }
void skip_filtered_fields() {
if (has_filtered_field()) {
while (_index >= 0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass, offset())) {
_index -= 1;
}
}
}
public:
FilteredFieldStream(InstanceKlass* klass, bool local_only, bool classes_only)
: FieldStream(klass, local_only, classes_only) {
_filtered_fields_count = FilteredFieldsMap::filtered_fields_count(klass, local_only);
// skip filtered fields at the end
skip_filtered_fields();
}
int field_count();
void next() {
_index -= 1;
if (has_filtered_field()) {
while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass, offset())) {
_index -= 1;
}
}
skip_filtered_fields();
}
};

@ -0,0 +1,60 @@
/*
* Copyright (c) 2023, 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.
*/
/*
* @test
* @bug 8318626
* @summary Verifies JVMTI GetClassFields function filters out fields
* the same way Class.getDeclaredFields() does.
*
* @run main/othervm/native -agentlib:FilteredFieldsTest FilteredFieldsTest
*/
import java.lang.reflect.Field;
public class FilteredFieldsTest {
static {
System.loadLibrary("FilteredFieldsTest");
}
private native static int getJVMTIFieldCount(Class cls);
private static int getDeclaredFieldsCount(Class cls) {
Field[] declaredFields = cls.getDeclaredFields();
System.out.println("Class.getDeclaredFields reported " + declaredFields.length + " fields:");
for (int i = 0; i < declaredFields.length; i++) {
System.out.println(" [" + i + "] : " + declaredFields[i]);
}
return declaredFields.length;
}
public static void main(String args[]) throws Exception {
Class cls = Class.forName("jdk.internal.reflect.ConstantPool");
int declaredCount = getDeclaredFieldsCount(cls);
int jvmtiCount = getJVMTIFieldCount(cls);
if (declaredCount != jvmtiCount) {
throw new Exception("declaredCount != jvmtiCount: " + declaredCount + " != " + jvmtiCount);
}
}
}

@ -0,0 +1,79 @@
/*
* Copyright (c) 2023, 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 <stdio.h>
#include <string.h>
#include "jvmti.h"
#include "jvmti_common.h"
extern "C" {
static jvmtiEnv *jvmti = NULL;
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
jint res = jvm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1);
if (res != JNI_OK || jvmti == NULL) {
printf("Wrong result of a valid call to GetEnv!\n");
fflush(0);
return JNI_ERR;
}
return JNI_OK;
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT jint JNICALL
Java_FilteredFieldsTest_getJVMTIFieldCount(JNIEnv *env, jclass cls, jclass clazz) {
if (jvmti == NULL) {
env->FatalError("JVMTI agent was not properly loaded");
}
jint fcount = 0;
jfieldID *fields = nullptr;
check_jvmti_status(env, jvmti->GetClassFields(clazz, &fcount, &fields), "GetClassFields failed");
printf("GetClassFields returned %d fields:\n", (int)fcount);
for (int i = 0; i < fcount; i++) {
char *name;
jvmtiError err = jvmti->GetFieldName(clazz, fields[i], &name, nullptr, nullptr);
if (err != JVMTI_ERROR_NONE) {
printf("GetFieldName(%d) returned error: %s (%d)\n",
i, TranslateError(err), err);
continue;
}
printf(" [%d]: %s\n", i, name);
jvmti->Deallocate((unsigned char *)name);
}
fflush(0);
return fcount;
}
}