mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8371083: FollowReferences reports non-class objects as JVMTI_HEAP_REFERENCE_SYSTEM_CLASS
Reviewed-by: lmesnik, sspitsyn
This commit is contained in:
parent
58b601ac42
commit
3924a28a22
@ -2190,6 +2190,39 @@ class SimpleRootsClosure : public OopClosure {
|
||||
virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
|
||||
};
|
||||
|
||||
// A supporting closure used to process ClassLoaderData roots.
|
||||
class CLDRootsClosure: public OopClosure {
|
||||
private:
|
||||
bool _continue;
|
||||
public:
|
||||
CLDRootsClosure(): _continue(true) {}
|
||||
|
||||
inline bool stopped() {
|
||||
return !_continue;
|
||||
}
|
||||
|
||||
void do_oop(oop* obj_p) {
|
||||
if (stopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
oop o = NativeAccess<AS_NO_KEEPALIVE>::oop_load(obj_p);
|
||||
// ignore null
|
||||
if (o == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
jvmtiHeapReferenceKind kind = JVMTI_HEAP_REFERENCE_OTHER;
|
||||
if (o->klass() == vmClasses::Class_klass()) {
|
||||
kind = JVMTI_HEAP_REFERENCE_SYSTEM_CLASS;
|
||||
}
|
||||
|
||||
// invoke the callback
|
||||
_continue = CallbackInvoker::report_simple_root(kind, o);
|
||||
}
|
||||
virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
|
||||
};
|
||||
|
||||
// A supporting closure used to process JNI locals
|
||||
class JNILocalRootsClosure : public OopClosure {
|
||||
private:
|
||||
@ -2776,10 +2809,10 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() {
|
||||
}
|
||||
|
||||
// Preloaded classes and loader from the system dictionary
|
||||
blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS);
|
||||
CLDToOopClosure cld_closure(&blk, ClassLoaderData::_claim_none);
|
||||
CLDRootsClosure cld_roots_closure;
|
||||
CLDToOopClosure cld_closure(&cld_roots_closure, ClassLoaderData::_claim_none);
|
||||
ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
|
||||
if (blk.stopped()) {
|
||||
if (cld_roots_closure.stopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8371083
|
||||
* @summary Verify FollowReferences does not report non-classes roots as JVMTI_HEAP_REFERENCE_SYSTEM_CLASS
|
||||
* @requires vm.jvmti
|
||||
* @run main/othervm/native -agentlib:KindSystemClass
|
||||
* KindSystemClass
|
||||
*/
|
||||
|
||||
public class KindSystemClass {
|
||||
|
||||
static native int tagSysClasses();
|
||||
static native Object[] getObjectsWithTags();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.loadLibrary("KindSystemClass");
|
||||
|
||||
int tagged = tagSysClasses();
|
||||
System.out.println("Tagged " + tagged + " classes");
|
||||
|
||||
Object[] objs = getObjectsWithTags();
|
||||
System.out.println("Tagged objects (total " + objs.length + "):");
|
||||
int nonClassesCnt = 0;
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
Object obj = objs[i];
|
||||
String s;
|
||||
if (obj instanceof Class cls) {
|
||||
s = "OK: " + cls;
|
||||
} else {
|
||||
nonClassesCnt++;
|
||||
s = "ERROR, not a class: " + obj;
|
||||
}
|
||||
System.out.println("[" + i + "] " + s);
|
||||
}
|
||||
if (nonClassesCnt != 0) {
|
||||
throw new RuntimeException("Found " + nonClassesCnt + " non-classes");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 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 <jvmti.h>
|
||||
#include "jvmti_common.hpp"
|
||||
|
||||
static jvmtiEnv *jvmti = nullptr;
|
||||
static int class_counter = 0;
|
||||
static int other_counter = 0;
|
||||
|
||||
static jint JNICALL
|
||||
heap_reference_callback(jvmtiHeapReferenceKind reference_kind,
|
||||
const jvmtiHeapReferenceInfo* reference_info,
|
||||
jlong class_tag,
|
||||
jlong referrer_class_tag,
|
||||
jlong size,
|
||||
jlong* tag_ptr,
|
||||
jlong* referrer_tag_ptr,
|
||||
jint length,
|
||||
void* user_data) {
|
||||
switch (reference_kind) {
|
||||
case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS:
|
||||
*tag_ptr = ++class_counter;
|
||||
break;
|
||||
case JVMTI_HEAP_REFERENCE_OTHER:
|
||||
++other_counter;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return JVMTI_VISIT_OBJECTS;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_KindSystemClass_tagSysClasses(JNIEnv* jni, jclass clazz) {
|
||||
jvmtiHeapCallbacks callbacks = {};
|
||||
callbacks.heap_reference_callback = heap_reference_callback;
|
||||
|
||||
jvmtiError err = jvmti->FollowReferences(0 /* filter nothing */,
|
||||
nullptr /* no class filter */,
|
||||
nullptr /* no initial object, follow roots */,
|
||||
&callbacks,
|
||||
nullptr);
|
||||
check_jvmti_error(err, "FollowReferences failed");
|
||||
|
||||
LOG("JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: %d, JVMTI_HEAP_REFERENCE_OTHER: %d\n", class_counter, other_counter);
|
||||
|
||||
return class_counter;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobjectArray JNICALL
|
||||
Java_KindSystemClass_getObjectsWithTags(JNIEnv* jni, jclass clazz) {
|
||||
// request tagged objects with tags 1..class_counter
|
||||
jlong* tags = nullptr;
|
||||
jvmtiError err = jvmti->Allocate(class_counter * sizeof(jlong), (unsigned char**)&tags);
|
||||
check_jvmti_error(err, "Allocate failed");
|
||||
|
||||
for (int i = 0; i < class_counter; i++) {
|
||||
tags[i] = i + 1;
|
||||
}
|
||||
|
||||
jint count = 0;
|
||||
jobject* objects = nullptr;
|
||||
|
||||
err = jvmti->GetObjectsWithTags(class_counter, tags,
|
||||
&count, &objects, nullptr);
|
||||
check_jvmti_error(err, "GetObjectsWithTags failed");
|
||||
|
||||
jclass object_klass = jni->FindClass("java/lang/Object");
|
||||
jobjectArray array = jni->NewObjectArray(count, object_klass, nullptr);
|
||||
|
||||
for (jint i = 0; i < count; i++) {
|
||||
jni->SetObjectArrayElement(array, i, objects[i]);
|
||||
}
|
||||
|
||||
deallocate(jvmti, jni, objects);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&jvmti), JVMTI_VERSION) != JNI_OK || !jvmti) {
|
||||
LOG("Could not initialize JVMTI\n");
|
||||
abort();
|
||||
}
|
||||
jvmtiCapabilities capabilities;
|
||||
memset(&capabilities, 0, sizeof(capabilities));
|
||||
capabilities.can_tag_objects = 1;
|
||||
check_jvmti_error(jvmti->AddCapabilities(&capabilities), "adding capabilities");
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user