Skip to content
Permalink
Browse files

8227610: Remove allocation when getting EventHandle

Reviewed-by: mgronlun
  • Loading branch information
Erik Gahlin
Erik Gahlin committed Jan 27, 2020
1 parent e438fb4 commit 3884792cda8b841778a46d2c60c132b2d4680a44
@@ -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 jdk.internal.HotSpotIntrinsicCandidate;
import jdk.jfr.Event;
import jdk.jfr.internal.handlers.EventHandler;

/**
* Interface against the JVM.
@@ -562,4 +563,24 @@ public boolean hasNativeJFR() {
*/
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 @@ static long nanosToTicks(long nanos) {

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

0 comments on commit 3884792

Please sign in to comment.