mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-19 14:55:17 +00:00
8227610: Remove allocation when getting EventHandle
Reviewed-by: mgronlun
This commit is contained in:
parent
e438fb4c62
commit
3884792cda
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -46,6 +46,7 @@
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/threadSMR.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
|
||||
#ifdef ASSERT
|
||||
void JfrJavaSupport::check_java_thread_in_vm(Thread* t) {
|
||||
@ -763,6 +764,74 @@ bool JfrJavaSupport::is_excluded(jobject thread) {
|
||||
return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread);
|
||||
}
|
||||
|
||||
jobject JfrJavaSupport::get_handler(jobject clazz, Thread* thread) {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
const oop klass_oop = JNIHandles::resolve(clazz);
|
||||
assert(klass_oop != NULL, "invariant");
|
||||
Klass* klass = java_lang_Class::as_Klass(klass_oop);
|
||||
HandleMark hm(thread);
|
||||
Handle h_klass_oop(Handle(thread, klass->java_mirror()));
|
||||
InstanceKlass* const instance_klass = static_cast<InstanceKlass*>(klass);
|
||||
assert(instance_klass->is_initialized(), "inavarient");
|
||||
|
||||
fieldDescriptor event_handler_field;
|
||||
Klass* f = instance_klass->find_field(
|
||||
vmSymbols::eventHandler_name(),
|
||||
vmSymbols::jdk_jfr_internal_handlers_EventHandler_signature(),
|
||||
true, &event_handler_field);
|
||||
if (f != NULL) {
|
||||
oop ret = h_klass_oop->obj_field(event_handler_field.offset());
|
||||
return ret != NULL ? JfrJavaSupport::local_jni_handle(ret, thread) : NULL;
|
||||
}
|
||||
|
||||
fieldDescriptor object_field;
|
||||
Klass* g = instance_klass->find_field(
|
||||
vmSymbols::eventHandler_name(),
|
||||
vmSymbols::object_signature(),
|
||||
true, &object_field);
|
||||
if (g != NULL) {
|
||||
oop ret = h_klass_oop->obj_field(object_field.offset());
|
||||
return ret != NULL ? JfrJavaSupport::local_jni_handle(ret, thread) : NULL;
|
||||
}
|
||||
assert(f == NULL && g == NULL, "no handler field for class");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool JfrJavaSupport::set_handler(jobject clazz, jobject handler, Thread* thread) {
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
const oop klass_oop = JNIHandles::resolve(clazz);
|
||||
assert(klass_oop != NULL, "invariant");
|
||||
const oop handler_oop = JNIHandles::resolve(handler);
|
||||
assert(handler_oop != NULL, "invariant");
|
||||
Klass* klass = java_lang_Class::as_Klass(klass_oop);
|
||||
HandleMark hm(thread);
|
||||
Handle h_klass_oop(Handle(thread, klass->java_mirror()));
|
||||
InstanceKlass* const instance_klass = static_cast<InstanceKlass*>(klass);
|
||||
assert(instance_klass->is_initialized(), "inavarient");
|
||||
|
||||
fieldDescriptor event_handler_field;
|
||||
Klass* f = instance_klass->find_field(
|
||||
vmSymbols::eventHandler_name(),
|
||||
vmSymbols::jdk_jfr_internal_handlers_EventHandler_signature(),
|
||||
true, &event_handler_field);
|
||||
if (f != NULL) {
|
||||
h_klass_oop->obj_field_put(event_handler_field.offset(), handler_oop);
|
||||
return true;
|
||||
}
|
||||
|
||||
fieldDescriptor object_handler_field;
|
||||
Klass* g = instance_klass->find_field(
|
||||
vmSymbols::eventHandler_name(),
|
||||
vmSymbols::object_signature(),
|
||||
true, &object_handler_field);
|
||||
if (g != NULL) {
|
||||
h_klass_oop->obj_field_put(object_handler_field.offset(), handler_oop);
|
||||
return true;
|
||||
}
|
||||
assert(f == NULL && g == NULL, "no handler field for class");
|
||||
return false;
|
||||
}
|
||||
|
||||
void JfrJavaSupport::on_thread_start(Thread* t) {
|
||||
assert(t != NULL, "invariant");
|
||||
assert(Thread::current() == t, "invariant");
|
||||
|
||||
@ -95,6 +95,9 @@ class JfrJavaSupport : public AllStatic {
|
||||
static bool is_excluded(jobject thread);
|
||||
static void on_thread_start(Thread* t);
|
||||
|
||||
static jobject get_handler(jobject clazz, Thread* thread);
|
||||
static bool set_handler(jobject clazz, jobject handler, Thread* thread);
|
||||
|
||||
// critical
|
||||
static void abort(jstring errorMsg, TRAPS);
|
||||
static void uncaught_exception(jthrowable throwable, Thread* t);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -341,3 +341,12 @@ JVM_ENTRY_NO_ENV(jlong, jfr_chunk_start_nanos(JNIEnv* env, jobject jvm))
|
||||
return JfrRepository::current_chunk_start_nanos();
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY_NO_ENV(jobject, jfr_get_handler(JNIEnv * env, jobject jvm, jobject clazz))
|
||||
return JfrJavaSupport::get_handler(clazz, thread);
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY_NO_ENV(jboolean, jfr_set_handler(JNIEnv * env, jobject jvm, jobject clazz, jobject handler))
|
||||
return JfrJavaSupport::set_handler(clazz, handler, thread);
|
||||
JVM_END
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -144,6 +144,11 @@ jboolean JNICALL jfr_is_thread_excluded(JNIEnv* env, jobject jvm, jobject t);
|
||||
|
||||
jlong JNICALL jfr_chunk_start_nanos(JNIEnv* env, jobject jvm);
|
||||
|
||||
jobject JNICALL jfr_get_handler(JNIEnv* env, jobject jvm, jobject clazz);
|
||||
|
||||
jboolean JNICALL jfr_set_handler(JNIEnv* env, jobject jvm, jobject clazz, jobject handler);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -86,7 +86,9 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
|
||||
(char*)"exclude", (char*)"(Ljava/lang/Thread;)V", (void*)jfr_exclude_thread,
|
||||
(char*)"include", (char*)"(Ljava/lang/Thread;)V", (void*)jfr_include_thread,
|
||||
(char*)"isExcluded", (char*)"(Ljava/lang/Thread;)Z", (void*)jfr_is_thread_excluded,
|
||||
(char*)"getChunkStartNanos", (char*)"()J", (void*)jfr_chunk_start_nanos
|
||||
(char*)"getChunkStartNanos", (char*)"()J", (void*)jfr_chunk_start_nanos,
|
||||
(char*)"getHandler", (char*)"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)jfr_get_handler,
|
||||
(char*)"setHandler", (char*)"(Ljava/lang/Class;Ljdk/jfr/internal/handlers/EventHandler;)Z", (void*)jfr_set_handler
|
||||
};
|
||||
|
||||
const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);
|
||||
|
||||
@ -34,7 +34,9 @@
|
||||
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp"
|
||||
|
||||
#define JFR_TEMPLATES(template) \
|
||||
template(jdk_jfr_internal_JVM, "jdk/jfr/internal/JVM")
|
||||
template(jdk_jfr_internal_JVM, "jdk/jfr/internal/JVM") \
|
||||
template(jdk_jfr_internal_handlers_EventHandler_signature, "Ljdk/jfr/internal/handlers/EventHandler;") \
|
||||
template(eventHandler_name, "eventHandler") \
|
||||
|
||||
#define JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \
|
||||
do_intrinsic(_counterTime, jdk_jfr_internal_JVM, counterTime_name, void_long_signature, F_SN) \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -30,6 +30,7 @@ import java.util.List;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.jfr.Event;
|
||||
import jdk.jfr.internal.handlers.EventHandler;
|
||||
|
||||
/**
|
||||
* Interface against the JVM.
|
||||
@ -562,4 +563,24 @@ public final class JVM {
|
||||
*/
|
||||
public native long getChunkStartNanos();
|
||||
|
||||
/**
|
||||
* Stores an EventHandler to the eventHandler field of an event class.
|
||||
*
|
||||
* @param eventClass the class, not {@code null}
|
||||
*
|
||||
* @param handler the handler, may be {@code null}
|
||||
*
|
||||
* @return if the field could be set
|
||||
*/
|
||||
public native boolean setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler);
|
||||
|
||||
/**
|
||||
* Retrieves the EventHandler for an event class.
|
||||
*
|
||||
* @param eventClass the class, not {@code null}
|
||||
*
|
||||
* @return the handler, may be {@code null}
|
||||
*/
|
||||
public native Object getHandler(Class<? extends jdk.internal.event.Event> eventClass);
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -328,23 +328,17 @@ public final class Utils {
|
||||
|
||||
static synchronized EventHandler getHandler(Class<? extends jdk.internal.event.Event> eventClass) {
|
||||
Utils.ensureValidEventSubclass(eventClass);
|
||||
try {
|
||||
Field f = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER);
|
||||
SecuritySupport.setAccessible(f);
|
||||
return (EventHandler) f.get(null);
|
||||
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new InternalError("Could not access event handler");
|
||||
Object handler = JVM.getJVM().getHandler(eventClass);
|
||||
if (handler == null || handler instanceof EventHandler) {
|
||||
return (EventHandler) handler;
|
||||
}
|
||||
throw new InternalError("Could not access event handler");
|
||||
}
|
||||
|
||||
static synchronized void setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler) {
|
||||
Utils.ensureValidEventSubclass(eventClass);
|
||||
try {
|
||||
Field field = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER);
|
||||
SecuritySupport.setAccessible(field);
|
||||
field.set(null, handler);
|
||||
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new InternalError("Could not access event handler");
|
||||
if (!JVM.getJVM().setHandler(eventClass, handler)) {
|
||||
throw new InternalError("Could not set event handler");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,15 @@ public class TestSecurityPropertyModificationEvent {
|
||||
static String keyValue = "shouldBecomeAnEvent";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// If events in java.base are used before JFR is initialized
|
||||
// the event handler field will be of type java.lang.Object.
|
||||
// Adding this for one of the security events makes sure
|
||||
// we have test coverage of this mode as well.
|
||||
for (String key : keys) {
|
||||
Security.setProperty(key, keyValue);
|
||||
}
|
||||
|
||||
try (Recording recording = new Recording()) {
|
||||
recording.enable(EventNames.SecurityProperty);
|
||||
recording.start();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user