OpenJDK / jdk / jdk
changeset 57840:4b2d33292638
8227610: Remove allocation when getting EventHandle
Reviewed-by: mgronlun
author | egahlin |
---|---|
date | Mon, 27 Jan 2020 14:30:57 +0100 |
parents | 62d7f4566b6d |
children | 5d49b846aef7 |
files | src/hotspot/share/jfr/jni/jfrJavaSupport.cpp src/hotspot/share/jfr/jni/jfrJavaSupport.hpp src/hotspot/share/jfr/jni/jfrJniMethod.cpp src/hotspot/share/jfr/jni/jfrJniMethod.hpp src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp src/hotspot/share/jfr/support/jfrIntrinsics.hpp src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java test/jdk/jdk/jfr/event/security/TestSecurityPropertyModificationEvent.java |
diffstat | 9 files changed, 134 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp Mon Jan 27 14:30:57 2020 +0100 @@ -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 @@ 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");
--- a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp Mon Jan 27 14:30:57 2020 +0100 @@ -95,6 +95,9 @@ 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);
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp Mon Jan 27 14:30:57 2020 +0100 @@ -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 @@ 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 + +
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp Mon Jan 27 14:30:57 2020 +0100 @@ -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 @@ 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
--- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp Mon Jan 27 14:30:57 2020 +0100 @@ -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 @@ (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);
--- a/src/hotspot/share/jfr/support/jfrIntrinsics.hpp Fri Jan 24 10:16:35 2020 +0100 +++ b/src/hotspot/share/jfr/support/jfrIntrinsics.hpp Mon Jan 27 14:30:57 2020 +0100 @@ -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) \
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Fri Jan 24 10:16:35 2020 +0100 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Mon Jan 27 14:30:57 2020 +0100 @@ -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 jdk.internal.HotSpotIntrinsicCandidate; import jdk.jfr.Event; +import jdk.jfr.internal.handlers.EventHandler; /** * Interface against the JVM. @@ -562,4 +563,24 @@ */ 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); + }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Fri Jan 24 10:16:35 2020 +0100 +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Mon Jan 27 14:30:57 2020 +0100 @@ -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 @@ 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"); } }
--- a/test/jdk/jdk/jfr/event/security/TestSecurityPropertyModificationEvent.java Fri Jan 24 10:16:35 2020 +0100 +++ b/test/jdk/jdk/jfr/event/security/TestSecurityPropertyModificationEvent.java Mon Jan 27 14:30:57 2020 +0100 @@ -48,6 +48,15 @@ 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();