8203629: Produce events in the JDK without a dependency on jdk.jfr
Reviewed-by: mgronlun
--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Tue Oct 30 15:17:58 2018 -0700
+++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Wed Oct 31 02:10:21 2018 +0100
@@ -27,6 +27,8 @@
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
#include "classfile/stackMapTable.hpp"
#include "classfile/verificationType.hpp"
#include "interpreter/bytecodes.hpp"
@@ -61,25 +63,26 @@
"J", // 1
"commit", // 2
"eventHandler", // 3
- "Ljdk/jfr/internal/handlers/EventHandler;", // 4
- "duration", // 5
- "begin", // 6
- "()V", // 7
- "isEnabled", // 8
- "()Z", // 9
- "end", // 10
- "shouldCommit", // 11
- "startTime", // 12
- "<clinit>", // 13
- "jdk/jfr/FlightRecorder", // 14
- "register", // 15
- "(Ljava/lang/Class;)V", // 16 // LAST_REQUIRED_UTF8
- "StackMapTable", // 17
- "Exceptions", // 18
+ "duration", // 4
+ "begin", // 5
+ "()V", // 6
+ "isEnabled", // 7
+ "()Z", // 8
+ "end", // 9
+ "shouldCommit", // 10
+ "startTime", // 11 // LAST_REQUIRED_UTF8
+ "Ljdk/jfr/internal/handlers/EventHandler;", // 12
+ "Ljava/lang/Object;", // 13
+ "<clinit>", // 14
+ "jdk/jfr/FlightRecorder", // 15
+ "register", // 16
+ "(Ljava/lang/Class;)V", // 17
+ "StackMapTable", // 18
+ "Exceptions", // 19
"LineNumberTable", // 20
"LocalVariableTable", // 21
"LocalVariableTypeTable", // 22
- "RuntimeVisibleAnnotation" // 23
+ "RuntimeVisibleAnnotation", // 23
};
enum utf8_req_symbols {
@@ -87,7 +90,6 @@
UTF8_REQ_J_FIELD_DESC,
UTF8_REQ_commit,
UTF8_REQ_eventHandler,
- UTF8_REQ_eventHandler_FIELD_DESC,
UTF8_REQ_duration,
UTF8_REQ_begin,
UTF8_REQ_EMPTY_VOID_METHOD_DESC,
@@ -96,15 +98,17 @@
UTF8_REQ_end,
UTF8_REQ_shouldCommit,
UTF8_REQ_startTime,
- UTF8_REQ_clinit,
- UTF8_REQ_FlightRecorder,
- UTF8_REQ_register,
- UTF8_REQ_CLASS_VOID_METHOD_DESC,
NOF_UTF8_REQ_SYMBOLS
};
enum utf8_opt_symbols {
- UTF8_OPT_StackMapTable = NOF_UTF8_REQ_SYMBOLS,
+ UTF8_OPT_eventHandler_FIELD_DESC = NOF_UTF8_REQ_SYMBOLS,
+ UTF8_OPT_LjavaLangObject,
+ UTF8_OPT_clinit,
+ UTF8_OPT_FlightRecorder,
+ UTF8_OPT_register,
+ UTF8_OPT_CLASS_VOID_METHOD_DESC,
+ UTF8_OPT_StackMapTable,
UTF8_OPT_Exceptions,
UTF8_OPT_LineNumberTable,
UTF8_OPT_LocalVariableTable,
@@ -353,7 +357,7 @@
static unsigned int unused_hash = 0;
static const char value_name[] = "value";
-static bool has_registered_annotation(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
+static bool has_annotation(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
assert(annotation_type != NULL, "invariant");
AnnotationArray* class_annotations = ik->class_annotations();
if (class_annotations == NULL) {
@@ -383,16 +387,51 @@
return false;
}
-static bool registered_annotation_value(const InstanceKlass* ik, const Symbol* const registered_symbol) {
- assert(registered_symbol != NULL, "invariant");
+// Evaluate to the value of the first found Symbol* annotation type.
+// Searching moves upwards in the klass hierarchy in order to support
+// inherited annotations in addition to the ability to override.
+static bool annotation_value(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
assert(ik != NULL, "invariant");
+ assert(annotation_type != NULL, "invariant");
assert(JdkJfrEvent::is_a(ik), "invariant");
- bool registered_value = false;
- if (has_registered_annotation(ik, registered_symbol, registered_value)) {
- return registered_value;
+ if (has_annotation(ik, annotation_type, value)) {
+ return true;
+ }
+ InstanceKlass* const super = InstanceKlass::cast(ik->super());
+ return super != NULL && JdkJfrEvent::is_a(super) ? annotation_value(super, annotation_type, value) : false;
+}
+
+static const char jdk_jfr_module_name[] = "jdk.jfr";
+
+static bool java_base_can_read_jdk_jfr() {
+ static bool can_read = false;
+ if (can_read) {
+ return true;
}
- InstanceKlass* super = InstanceKlass::cast(ik->super());
- return registered_annotation_value(super, registered_symbol);
+ static Symbol* jdk_jfr_module_symbol = NULL;
+ if (jdk_jfr_module_symbol == NULL) {
+ jdk_jfr_module_symbol = SymbolTable::lookup_only(jdk_jfr_module_name, sizeof jdk_jfr_module_name - 1, unused_hash);
+ if (jdk_jfr_module_symbol == NULL) {
+ return false;
+ }
+ }
+ assert(jdk_jfr_module_symbol != NULL, "invariant");
+ ModuleEntryTable* const table = Modules::get_module_entry_table(Handle());
+ assert(table != NULL, "invariant");
+ const ModuleEntry* const java_base_module = table->javabase_moduleEntry();
+ if (java_base_module == NULL) {
+ return false;
+ }
+ assert(java_base_module != NULL, "invariant");
+ ModuleEntry* const jdk_jfr_module = table->lookup_only(jdk_jfr_module_symbol);
+ if (jdk_jfr_module == NULL) {
+ return false;
+ }
+ assert(jdk_jfr_module != NULL, "invariant");
+ if (java_base_module->can_read(jdk_jfr_module)) {
+ can_read = true;
+ }
+ return can_read;
}
static const char registered_constant[] = "Ljdk/jfr/Registered;";
@@ -400,13 +439,23 @@
// Evaluate to the value of the first found "Ljdk/jfr/Registered;" annotation.
// Searching moves upwards in the klass hierarchy in order to support
// inherited annotations in addition to the ability to override.
-static bool should_register_klass(const InstanceKlass* ik) {
- static const Symbol* const registered_symbol = SymbolTable::lookup_only(registered_constant,
- sizeof registered_constant - 1,
- unused_hash);
+static bool should_register_klass(const InstanceKlass* ik, bool& untypedEventHandler) {
+ assert(ik != NULL, "invariant");
+ assert(JdkJfrEvent::is_a(ik), "invariant");
+ assert(!untypedEventHandler, "invariant");
+ static const Symbol* registered_symbol = NULL;
+ if (registered_symbol == NULL) {
+ registered_symbol = SymbolTable::lookup_only(registered_constant, sizeof registered_constant - 1, unused_hash);
+ if (registered_symbol == NULL) {
+ return false;
+ }
+ }
assert(registered_symbol != NULL, "invariant");
- return registered_annotation_value(ik, registered_symbol);
+ bool value = false; // to be set by annotation_value
+ untypedEventHandler = !(annotation_value(ik, registered_symbol, value) || java_base_can_read_jdk_jfr());
+ return value;
}
+
/*
* Map an utf8 constant back to its CONSTANT_UTF8_INFO
*/
@@ -450,6 +499,9 @@
u2 orig_cp_len,
u2& number_of_new_constants,
TRAPS) {
+ assert(cls_name_index != invalid_cp_index, "invariant");
+ assert(method_index != invalid_cp_index, "invariant");
+ assert(desc_index != invalid_cp_index, "invariant");
assert(is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants), "invariant");
assert(is_index_within_range(method_index, orig_cp_len, number_of_new_constants), "invariant");
assert(is_index_within_range(desc_index, orig_cp_len, number_of_new_constants), "invariant");
@@ -477,9 +529,9 @@
TRAPS) {
assert(utf8_indexes != NULL, "invariant");
return add_method_ref_info(writer,
- utf8_indexes[UTF8_REQ_FlightRecorder],
- utf8_indexes[UTF8_REQ_register],
- utf8_indexes[UTF8_REQ_CLASS_VOID_METHOD_DESC],
+ utf8_indexes[UTF8_OPT_FlightRecorder],
+ utf8_indexes[UTF8_OPT_register],
+ utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC],
orig_cp_len,
number_of_new_constants,
THREAD);
@@ -495,8 +547,8 @@
* }
*/
static jlong add_field_info(JfrBigEndianWriter& writer, u2 name_index, u2 desc_index, bool is_static = false) {
- assert(name_index > 0, "invariant");
- assert(desc_index > 0, "invariant");
+ assert(name_index != invalid_cp_index, "invariant");
+ assert(desc_index != invalid_cp_index, "invariant");
DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PRIVATE | (is_static ? JVM_ACC_STATIC : JVM_ACC_TRANSIENT)); // flags
writer.write(name_index);
@@ -507,11 +559,11 @@
return writer.current_offset();
}
-static u2 add_field_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes) {
+static u2 add_field_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes, bool untypedEventHandler) {
assert(utf8_indexes != NULL, "invariant");
add_field_info(writer,
utf8_indexes[UTF8_REQ_eventHandler],
- utf8_indexes[UTF8_REQ_eventHandler_FIELD_DESC],
+ untypedEventHandler ? utf8_indexes[UTF8_OPT_LjavaLangObject] : utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC],
true); // static
add_field_info(writer,
@@ -989,7 +1041,8 @@
// This is to ensure that padding can be done
// where needed and to simplify size calculations.
static const u2 injected_code_length = 8;
- const u2 name_index = utf8_indexes[UTF8_REQ_clinit];
+ const u2 name_index = utf8_indexes[UTF8_OPT_clinit];
+ assert(name_index != invalid_cp_index, "invariant");
const u2 desc_index = utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC];
const u2 max_stack = MAX2(clinit_method != NULL ? clinit_method->verifier_max_stack() : 1, 1);
const u2 max_locals = MAX2(clinit_method != NULL ? clinit_method->max_locals() : 0, 0);
@@ -1138,59 +1191,58 @@
u2* const utf8_indexes,
u2 orig_cp_len,
const Method* clinit_method,
+ bool register_klass,
+ bool untypedEventHandler,
TRAPS) {
assert(utf8_indexes != NULL, "invariant");
u2 added_cp_entries = 0;
// resolve all required symbols
for (u2 index = 0; index < NOF_UTF8_REQ_SYMBOLS; ++index) {
- utf8_indexes[index] = find_or_add_utf8_info(writer,
- ik,
- utf8_constants[index],
- orig_cp_len,
- added_cp_entries,
- THREAD);
+ utf8_indexes[index] = find_or_add_utf8_info(writer, ik, utf8_constants[index], orig_cp_len, added_cp_entries, THREAD);
}
- // Now determine optional constants (mainly "Code" attributes)
+
+ // resolve optional constants
+ utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC] = untypedEventHandler ? invalid_cp_index :
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_eventHandler_FIELD_DESC], orig_cp_len, added_cp_entries, THREAD);
+
+ utf8_indexes[UTF8_OPT_LjavaLangObject] = untypedEventHandler ?
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LjavaLangObject], orig_cp_len, added_cp_entries, THREAD) : invalid_cp_index;
+
+ if (register_klass) {
+ utf8_indexes[UTF8_OPT_clinit] =
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_clinit], orig_cp_len, added_cp_entries, THREAD);
+ utf8_indexes[UTF8_OPT_FlightRecorder] =
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_FlightRecorder], orig_cp_len, added_cp_entries, THREAD);
+ utf8_indexes[UTF8_OPT_register] =
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_register], orig_cp_len, added_cp_entries, THREAD);
+ utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] =
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_CLASS_VOID_METHOD_DESC], orig_cp_len, added_cp_entries, THREAD);
+ } else {
+ utf8_indexes[UTF8_OPT_clinit] = invalid_cp_index;
+ utf8_indexes[UTF8_OPT_FlightRecorder] = invalid_cp_index;
+ utf8_indexes[UTF8_OPT_register] = invalid_cp_index;
+ utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] = invalid_cp_index;
+ }
+
if (clinit_method != NULL && clinit_method->has_stackmap_table()) {
utf8_indexes[UTF8_OPT_StackMapTable] =
- find_or_add_utf8_info(writer,
- ik,
- utf8_constants[UTF8_OPT_StackMapTable],
- orig_cp_len,
- added_cp_entries,
- THREAD);
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_StackMapTable], orig_cp_len, added_cp_entries, THREAD);
} else {
utf8_indexes[UTF8_OPT_StackMapTable] = invalid_cp_index;
}
if (clinit_method != NULL && clinit_method->has_linenumber_table()) {
utf8_indexes[UTF8_OPT_LineNumberTable] =
- find_or_add_utf8_info(writer,
- ik,
- utf8_constants[UTF8_OPT_LineNumberTable],
- orig_cp_len,
- added_cp_entries,
- THREAD);
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LineNumberTable], orig_cp_len, added_cp_entries, THREAD);
} else {
utf8_indexes[UTF8_OPT_LineNumberTable] = invalid_cp_index;
}
if (clinit_method != NULL && clinit_method->has_localvariable_table()) {
utf8_indexes[UTF8_OPT_LocalVariableTable] =
- find_or_add_utf8_info(writer,
- ik,
- utf8_constants[UTF8_OPT_LocalVariableTable],
- orig_cp_len,
- added_cp_entries,
- THREAD);
-
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTable], orig_cp_len, added_cp_entries, THREAD);
utf8_indexes[UTF8_OPT_LocalVariableTypeTable] =
- find_or_add_utf8_info(writer,
- ik,
- utf8_constants[UTF8_OPT_LocalVariableTypeTable],
- orig_cp_len,
- added_cp_entries,
- THREAD);
+ find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTypeTable], orig_cp_len, added_cp_entries, THREAD);
} else {
utf8_indexes[UTF8_OPT_LocalVariableTable] = invalid_cp_index;
utf8_indexes[UTF8_OPT_LocalVariableTypeTable] = invalid_cp_index;
@@ -1207,7 +1259,8 @@
// If the class already has a clinit method
// we need to take that into account
const Method* clinit_method = ik->class_initializer();
- const bool register_klass = should_register_klass(ik);
+ bool untypedEventHandler = false;
+ const bool register_klass = should_register_klass(ik, untypedEventHandler);
const ClassFileStream* const orig_stream = parser.clone_stream();
const int orig_stream_size = orig_stream->length();
assert(orig_stream->current_offset() == 0, "invariant");
@@ -1241,7 +1294,8 @@
// Resolve_utf8_indexes will be conservative in attempting to
// locate an existing UTF8_INFO; it will only append constants
// that is absolutely required
- u2 number_of_new_constants = resolve_utf8_indexes(writer, ik, utf8_indexes, orig_cp_len, clinit_method, THREAD);
+ u2 number_of_new_constants =
+ resolve_utf8_indexes(writer, ik, utf8_indexes, orig_cp_len, clinit_method, register_klass, untypedEventHandler, THREAD);
// UTF8_INFO entries now added to the constant pool
// In order to invoke a method we would need additional
// constants, JVM_CONSTANT_Class, JVM_CONSTANT_NameAndType
@@ -1274,7 +1328,7 @@
assert(writer.is_valid(), "invariant");
// We are sitting just after the original number of field_infos
// so this is a position where we can add (append) new field_infos
- const u2 number_of_new_fields = add_field_infos(writer, utf8_indexes);
+ const u2 number_of_new_fields = add_field_infos(writer, utf8_indexes, untypedEventHandler);
assert(writer.is_valid(), "invariant");
const jlong new_method_len_offset = writer.current_offset();
// Additional field_infos added, update classfile fields_count
--- a/src/hotspot/share/jfr/jni/jfrGetAllEventClasses.cpp Tue Oct 30 15:17:58 2018 -0700
+++ b/src/hotspot/share/jfr/jni/jfrGetAllEventClasses.cpp Wed Oct 31 02:10:21 2018 +0100
@@ -132,7 +132,7 @@
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
initialize(THREAD);
assert(empty_java_util_arraylist != NULL, "should have been setup already!");
- static const char jdk_jfr_event_name[] = "jdk/jfr/Event";
+ static const char jdk_jfr_event_name[] = "jdk/internal/event/Event";
unsigned int unused_hash = 0;
Symbol* const event_klass_name = SymbolTable::lookup_only(jdk_jfr_event_name, sizeof jdk_jfr_event_name - 1, unused_hash);
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp Tue Oct 30 15:17:58 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp Wed Oct 31 02:10:21 2018 +0100
@@ -76,22 +76,43 @@
return atomic_inc(&cld_id_counter) << TRACE_ID_SHIFT;
}
+static bool found_jdk_internal_event_klass = false;
static bool found_jdk_jfr_event_klass = false;
static void check_klass(const Klass* klass) {
assert(klass != NULL, "invariant");
- if (found_jdk_jfr_event_klass) {
+ if (found_jdk_internal_event_klass && found_jdk_jfr_event_klass) {
return;
}
+ static const Symbol* jdk_internal_event_sym = NULL;
+ if (jdk_internal_event_sym == NULL) {
+ // setup when loading the first TypeArrayKlass (Universe::genesis) hence single threaded invariant
+ jdk_internal_event_sym = SymbolTable::new_permanent_symbol("jdk/internal/event/Event", Thread::current());
+ }
+ assert(jdk_internal_event_sym != NULL, "invariant");
+
static const Symbol* jdk_jfr_event_sym = NULL;
if (jdk_jfr_event_sym == NULL) {
// setup when loading the first TypeArrayKlass (Universe::genesis) hence single threaded invariant
jdk_jfr_event_sym = SymbolTable::new_permanent_symbol("jdk/jfr/Event", Thread::current());
}
assert(jdk_jfr_event_sym != NULL, "invariant");
- if (jdk_jfr_event_sym == klass->name() && klass->class_loader() == NULL) {
- found_jdk_jfr_event_klass = true;
- JfrTraceId::tag_as_jdk_jfr_event(klass);
+ const Symbol* const klass_name = klass->name();
+
+ if (!found_jdk_internal_event_klass) {
+ if (jdk_internal_event_sym == klass_name && klass->class_loader() == NULL) {
+ found_jdk_internal_event_klass = true;
+ JfrTraceId::tag_as_jdk_jfr_event(klass);
+ return;
+ }
+ }
+
+ if (!found_jdk_jfr_event_klass) {
+ if (jdk_jfr_event_sym == klass_name && klass->class_loader() == NULL) {
+ found_jdk_jfr_event_klass = true;
+ JfrTraceId::tag_as_jdk_jfr_event(klass);
+ return;
+ }
}
}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp Tue Oct 30 15:17:58 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp Wed Oct 31 02:10:21 2018 +0100
@@ -112,10 +112,8 @@
inline void JfrTraceId::tag_as_jdk_jfr_event(const Klass* klass) {
assert(klass != NULL, "invariant");
- assert(IS_NOT_AN_EVENT_KLASS(klass), "invariant");
SET_TAG(klass, JDK_JFR_EVENT_KLASS);
assert(IS_JDK_JFR_EVENT_KLASS(klass), "invariant");
- assert(IS_NOT_AN_EVENT_SUB_KLASS(klass), "invariant");
}
inline bool JfrTraceId::is_jdk_jfr_event_sub(const Klass* k) {
@@ -125,7 +123,7 @@
inline void JfrTraceId::tag_as_jdk_jfr_event_sub(const Klass* k) {
assert(k != NULL, "invariant");
- if (IS_NOT_AN_EVENT_KLASS(k)) {
+ if (IS_NOT_AN_EVENT_SUB_KLASS(k)) {
SET_TAG(k, JDK_JFR_EVENT_SUBKLASS);
}
assert(IS_JDK_JFR_EVENT_SUBKLASS(k), "invariant");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/event/Event.java Wed Oct 31 02:10:21 2018 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.internal.event;
+
+/**
+ * Base class for events, to be subclassed in order to define events and their
+ * fields.
+ */
+public abstract class Event {
+ /**
+ * Sole constructor, for invocation by subclass constructors, typically
+ * implicit.
+ */
+ protected Event() {
+ }
+
+ /**
+ * Starts the timing of this event.
+ */
+ public void begin() {
+ }
+
+ /**
+ * Ends the timing of this event.
+ *
+ * The {@code end} method must be invoked after the {@code begin} method.
+ */
+ public void end() {
+ }
+
+ /**
+ * Writes the field values, time stamp, and event duration.
+ * <p>
+ * If the event starts with an invocation of the {@code begin} method, but does
+ * not end with an explicit invocation of the {@code end} method, then the event
+ * ends when the {@code commit} method is invoked.
+ */
+ public void commit() {
+ }
+
+ /**
+ * Returns {@code true} if the event is enabled, {@code false} otherwise
+ *
+ * @return {@code true} if event is enabled, {@code false} otherwise
+ */
+ public boolean isEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if the event is enabled and if the duration is within
+ * the threshold for the event, {@code false} otherwise.
+ *
+ * @return {@code true} if the event can be written, {@code false} otherwise
+ */
+ public boolean shouldCommit() {
+ return false;
+ }
+
+ /**
+ * Sets a field value.
+ *
+ * @param index the index of the field to set
+ * @param value value to set, can be {@code null}
+ * @throws UnsupportedOperationException if functionality is not supported
+ * @throws IndexOutOfBoundsException if {@code index} is less than {@code 0} or
+ * greater than or equal to the number of fields specified for the event
+ */
+ public void set(int index, Object value) {
+ }
+}
--- a/src/java.base/share/classes/module-info.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/java.base/share/classes/module-info.java Wed Oct 31 02:10:21 2018 +0100
@@ -136,6 +136,8 @@
java.security.sasl;
exports jdk.internal to
jdk.jfr;
+ exports jdk.internal.event to
+ jdk.jfr;
exports jdk.internal.jimage to
jdk.jlink;
exports jdk.internal.jimage.decompressor to
--- a/src/jdk.jfr/share/classes/jdk/jfr/Event.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/Event.java Wed Oct 31 02:10:21 2018 +0100
@@ -88,7 +88,7 @@
@Enabled(true)
@StackTrace(true)
@Registered(true)
-abstract public class Event {
+abstract public class Event extends jdk.internal.event.Event {
/**
* Sole constructor, for invocation by subclass constructors, typically
* implicit.
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java Wed Oct 31 02:10:21 2018 +0100
@@ -41,7 +41,6 @@
import jdk.internal.module.Modules;
import jdk.jfr.AnnotationElement;
import jdk.jfr.Enabled;
-import jdk.jfr.Event;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.SettingControl;
@@ -109,7 +108,7 @@
}
}
- EventControl(PlatformEventType es, Class<? extends Event> eventClass) {
+ EventControl(PlatformEventType es, Class<? extends jdk.internal.event.Event> eventClass) {
this(es);
defineSettings(eventClass);
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java Wed Oct 31 02:10:21 2018 +0100
@@ -93,11 +93,11 @@
return EventHandler.class.getName() + id + SUFFIX;
}
- public EventHandlerCreator(long id, List<SettingInfo> settingInfos, EventType type, Class<? extends Event> eventClass) {
+ public EventHandlerCreator(long id, List<SettingInfo> settingInfos, EventType type, Class<? extends jdk.internal.event.Event> eventClass) {
this(id, settingInfos, createFieldInfos(eventClass, type));
}
- private static List<FieldInfo> createFieldInfos(Class<? extends Event> eventClass, EventType type) throws Error {
+ private static List<FieldInfo> createFieldInfos(Class<? extends jdk.internal.event.Event> eventClass, EventType type) throws Error {
List<FieldInfo> fieldInfos = new ArrayList<>();
for (ValueDescriptor v : type.getFields()) {
// Only value descriptors that are not fields on the event class.
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java Wed Oct 31 02:10:21 2018 +0100
@@ -102,6 +102,7 @@
private static final Type ANNOTATION_TYPE_ENABLED = Type.getType(Enabled.class);
private static final Type TYPE_EVENT_HANDLER = Type.getType(EventHandler.class);
private static final Type TYPE_SETTING_CONTROL = Type.getType(SettingControl.class);
+ private static final Type TYPE_OBJECT = Type.getType(Object.class);
private static final Method METHOD_COMMIT = new Method("commit", Type.VOID_TYPE, new Type[0]);
private static final Method METHOD_BEGIN = new Method("begin", Type.VOID_TYPE, new Type[0]);
private static final Method METHOD_END = new Method("end", Type.VOID_TYPE, new Type[0]);
@@ -117,6 +118,7 @@
private final Method writeMethod;
private final String eventHandlerXInternalName;
private final String eventName;
+ private final boolean untypedEventHandler;
private boolean guardHandlerReference;
private Class<?> superClass;
@@ -125,11 +127,20 @@
this.classNode = createClassNode(bytes);
this.settingInfos = buildSettingInfos(superClass, classNode);
this.fieldInfos = buildFieldInfos(superClass, classNode);
+ this.untypedEventHandler = hasUntypedHandler();
this.writeMethod = makeWriteMethod(fieldInfos);
this.eventHandlerXInternalName = ASMToolkit.getInternalName(EventHandlerCreator.makeEventHandlerName(id));
String n = annotationValue(classNode, ANNOTATION_TYPE_NAME.getDescriptor(), String.class);
this.eventName = n == null ? classNode.name.replace("/", ".") : n;
+ }
+ private boolean hasUntypedHandler() {
+ for (FieldNode field : classNode.fields) {
+ if (FIELD_EVENT_HANDLER.equals(field.name)) {
+ return field.desc.equals(TYPE_OBJECT.getDescriptor());
+ }
+ }
+ throw new InternalError("Class missing handler field");
}
public String getClassName() {
@@ -225,7 +236,7 @@
}
}
}
- for (Class<?> c = superClass; c != Event.class; c = c.getSuperclass()) {
+ for (Class<?> c = superClass; c != jdk.internal.event.Event.class; c = c.getSuperclass()) {
for (java.lang.reflect.Method method : c.getDeclaredMethods()) {
if (!methodSet.contains(method.getName())) {
// skip private method in base classes
@@ -249,7 +260,6 @@
}
}
return settingInfos;
-
}
private static List<FieldInfo> buildFieldInfos(Class<?> superClass, ClassNode classNode) {
@@ -264,14 +274,13 @@
fieldInfos.add(new FieldInfo("startTime", Type.LONG_TYPE.getDescriptor(), classNode.name));
fieldInfos.add(new FieldInfo("duration", Type.LONG_TYPE.getDescriptor(), classNode.name));
for (FieldNode field : classNode.fields) {
- String className = Type.getType(field.desc).getClassName();
- if (!fieldSet.contains(field.name) && isValidField(field.access, className)) {
+ if (!fieldSet.contains(field.name) && isValidField(field.access, Type.getType(field.desc).getClassName())) {
FieldInfo fi = new FieldInfo(field.name, field.desc, classNode.name);
fieldInfos.add(fi);
fieldSet.add(field.name);
}
}
- for (Class<?> c = superClass; c != Event.class; c = c.getSuperclass()) {
+ for (Class<?> c = superClass; c != jdk.internal.event.Event.class; c = c.getSuperclass()) {
for (Field field : c.getDeclaredFields()) {
// skip private field in base classes
if (!Modifier.isPrivate(field.getModifiers())) {
@@ -321,10 +330,10 @@
updateMethod(METHOD_IS_ENABLED, methodVisitor -> {
Label nullLabel = new Label();
if (guardHandlerReference) {
- methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, TYPE_EVENT_HANDLER.getDescriptor());
+ getEventHandler(methodVisitor);
methodVisitor.visitJumpInsn(Opcodes.IFNULL, nullLabel);
}
- methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, TYPE_EVENT_HANDLER.getDescriptor());
+ getEventHandler(methodVisitor);
ASMToolkit.invokeVirtual(methodVisitor, TYPE_EVENT_HANDLER.getInternalName(), METHOD_IS_ENABLED);
methodVisitor.visitInsn(Opcodes.IRETURN);
if (guardHandlerReference) {
@@ -408,7 +417,7 @@
// eventHandler.write(...);
// }
methodVisitor.visitJumpInsn(Opcodes.IFEQ, end);
- methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, Type.getDescriptor(EventHandler.class));
+ getEventHandler(methodVisitor);
methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, eventHandlerXInternalName);
for (FieldInfo fi : fieldInfos) {
@@ -426,8 +435,8 @@
// MyEvent#shouldCommit()
updateMethod(METHOD_EVENT_SHOULD_COMMIT, methodVisitor -> {
Label fail = new Label();
- // if (!eventHandler.shoouldCommit(duration) goto fail;
- methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, Type.getDescriptor(EventHandler.class));
+ // if (!eventHandler.shouldCommit(duration) goto fail;
+ getEventHandler(methodVisitor);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, getInternalClassName(), FIELD_DURATION, "J");
ASMToolkit.invokeVirtual(methodVisitor, TYPE_EVENT_HANDLER.getInternalName(), METHOD_EVENT_HANDLER_SHOULD_COMMIT);
@@ -435,7 +444,11 @@
for (SettingInfo si : settingInfos) {
// if (!settingsMethod(eventHandler.settingX)) goto fail;
methodVisitor.visitIntInsn(Opcodes.ALOAD, 0);
- methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, Type.getDescriptor(EventHandler.class));
+ if (untypedEventHandler) {
+ methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, TYPE_OBJECT.getDescriptor());
+ } else {
+ methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, Type.getDescriptor(EventHandler.class));
+ }
methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, eventHandlerXInternalName);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, eventHandlerXInternalName, si.fieldName, TYPE_SETTING_CONTROL.getDescriptor());
methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, si.internalSettingName);
@@ -452,6 +465,15 @@
});
}
+ private void getEventHandler(MethodVisitor methodVisitor) {
+ if (untypedEventHandler) {
+ methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, TYPE_OBJECT.getDescriptor());
+ methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, TYPE_EVENT_HANDLER.getInternalName());
+ } else {
+ methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, getInternalClassName(), FIELD_EVENT_HANDLER, Type.getDescriptor(EventHandler.class));
+ }
+ }
+
private void makeUninstrumented() {
updateExistingWithReturnFalse(METHOD_EVENT_SHOULD_COMMIT);
updateExistingWithReturnFalse(METHOD_IS_ENABLED);
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java Wed Oct 31 02:10:21 2018 +0100
@@ -106,11 +106,11 @@
public native void endRecording();
/**
- * Return a list of all classes deriving from {@link Event}
+ * Return a list of all classes deriving from {@link jdk.internal.event.Event}
*
* @return list of event classes.
*/
- public native List<Class<? extends Event>> getAllEventClasses();
+ public native List<Class<? extends jdk.internal.event.Event>> getAllEventClasses();
/**
* Return a count of the number of unloaded classes deriving from {@link Event}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java Wed Oct 31 02:10:21 2018 +0100
@@ -26,7 +26,6 @@
import java.lang.reflect.Modifier;
-import jdk.jfr.Event;
import jdk.jfr.internal.handlers.EventHandler;
import jdk.jfr.internal.instrument.JDKEvents;
@@ -53,8 +52,8 @@
*/
static byte[] onRetransform(long traceId, boolean dummy, Class<?> clazz, byte[] oldBytes) throws Throwable {
try {
- if (Event.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) {
- EventHandler handler = Utils.getHandler(clazz.asSubclass(Event.class));
+ if (jdk.internal.event.Event.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) {
+ EventHandler handler = Utils.getHandler(clazz.asSubclass(jdk.internal.event.Event.class));
if (handler == null) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "No event handler found for " + clazz.getName() + ". Ignoring instrumentation request.");
// Probably triggered by some other agent
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java Wed Oct 31 02:10:21 2018 +0100
@@ -33,6 +33,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -56,6 +57,7 @@
private final List<EventControl> nativeControls = new ArrayList<EventControl>(100);
private final TypeLibrary typeLibrary = TypeLibrary.getInstance();
private final SettingsManager settingsManager = new SettingsManager();
+ private final Map<String, Class<? extends Event>> mirrors = new HashMap<>();
private boolean staleMetadata = true;
private boolean unregistered;
private long lastUnloaded = -1;
@@ -105,7 +107,7 @@
return eventTypes;
}
- public synchronized EventType getEventType(Class<? extends Event> eventClass) {
+ public synchronized EventType getEventType(Class<? extends jdk.internal.event.Event> eventClass) {
EventHandler h = getHandler(eventClass);
if (h != null && h.isRegistered()) {
return h.getEventType();
@@ -121,15 +123,20 @@
}
// never registered, ignore call
}
- public synchronized EventType register(Class<? extends Event> eventClass) {
+ public synchronized EventType register(Class<? extends jdk.internal.event.Event> eventClass) {
return register(eventClass, Collections.emptyList(), Collections.emptyList());
}
- public synchronized EventType register(Class<? extends Event> eventClass, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) {
+ public synchronized EventType register(Class<? extends jdk.internal.event.Event> eventClass, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) {
Utils.checkRegisterPermission();
EventHandler handler = getHandler(eventClass);
if (handler == null) {
- handler = makeHandler(eventClass, dynamicAnnotations, dynamicFields);
+ if (eventClass.getAnnotation(MirrorEvent.class) != null) {
+ // don't register mirrors
+ return null;
+ }
+ PlatformEventType pe = findMirrorType(eventClass);
+ handler = makeHandler(eventClass, pe, dynamicAnnotations, dynamicFields);
}
handler.setRegistered(true);
typeLibrary.addType(handler.getPlatformEventType());
@@ -143,16 +150,32 @@
return handler.getEventType();
}
- private EventHandler getHandler(Class<? extends Event> eventClass) {
+ private PlatformEventType findMirrorType(Class<? extends jdk.internal.event.Event> eventClass) throws InternalError {
+ String fullName = eventClass.getModule().getName() + ":" + eventClass.getName();
+ Class<? extends Event> mirrorClass = mirrors.get(fullName);
+ if (mirrorClass == null) {
+ return null; // not a mirror
+ }
+ Utils.verifyMirror(mirrorClass, eventClass);
+ PlatformEventType et = (PlatformEventType) TypeLibrary.createType(mirrorClass);
+ typeLibrary.removeType(et.getId());
+ long id = Type.getTypeId(eventClass);
+ et.setId(id);
+ return et;
+ }
+
+ private EventHandler getHandler(Class<? extends jdk.internal.event.Event> eventClass) {
Utils.ensureValidEventSubclass(eventClass);
SecuritySupport.makeVisibleToJFR(eventClass);
Utils.ensureInitialized(eventClass);
return Utils.getHandler(eventClass);
}
- private EventHandler makeHandler(Class<? extends Event> eventClass, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) throws InternalError {
+ private EventHandler makeHandler(Class<? extends jdk.internal.event.Event> eventClass, PlatformEventType pEventType, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) throws InternalError {
SecuritySupport.addHandlerExport(eventClass);
- PlatformEventType pEventType = (PlatformEventType) TypeLibrary.createType(eventClass, dynamicAnnotations, dynamicFields);
+ if (pEventType == null) {
+ pEventType = (PlatformEventType) TypeLibrary.createType(eventClass, dynamicAnnotations, dynamicFields);
+ }
EventType eventType = PrivateAccess.getInstance().newEventType(pEventType);
EventControl ec = new EventControl(pEventType, eventClass);
Class<? extends EventHandler> handlerClass = null;
@@ -198,9 +221,9 @@
}
private static List<EventHandler> getEventHandlers() {
- List<Class<? extends Event>> allEventClasses = jvm.getAllEventClasses();
+ List<Class<? extends jdk.internal.event.Event>> allEventClasses = jvm.getAllEventClasses();
List<EventHandler> eventHandlers = new ArrayList<>(allEventClasses.size());
- for (Class<? extends Event> clazz : allEventClasses) {
+ for (Class<? extends jdk.internal.event.Event> clazz : allEventClasses) {
EventHandler eh = Utils.getHandler(clazz);
if (eh != null) {
eventHandlers.add(eh);
@@ -252,9 +275,9 @@
long unloaded = jvm.getUnloadedEventClassCount();
if (this.lastUnloaded != unloaded) {
this.lastUnloaded = unloaded;
- List<Class<? extends Event>> eventClasses = jvm.getAllEventClasses();
+ List<Class<? extends jdk.internal.event.Event>> eventClasses = jvm.getAllEventClasses();
HashSet<Long> knownIds = new HashSet<>(eventClasses.size());
- for (Class<? extends Event> ec: eventClasses) {
+ for (Class<? extends jdk.internal.event.Event> ec: eventClasses) {
knownIds.add(Type.getTypeId(ec));
}
for (Type type : typeLibrary.getTypes()) {
@@ -270,8 +293,18 @@
}
}
- synchronized public void setUnregistered() {
+ synchronized void setUnregistered() {
unregistered = true;
}
+ public synchronized void registerMirror(Class<? extends Event> eventClass) {
+ MirrorEvent me = eventClass.getAnnotation(MirrorEvent.class);
+ if (me != null) {
+ String fullName = me.module() + ":" + me.className();
+ mirrors.put(fullName, eventClass);
+ return;
+ }
+ throw new InternalError("Mirror class must have annotation " + MirrorEvent.class.getName());
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvent.java Wed Oct 31 02:10:21 2018 +0100
@@ -0,0 +1,25 @@
+package jdk.jfr.internal;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface MirrorEvent {
+ /**
+ * Fully qualified name of the class to mirror metadata for (for example,
+ * {@code "jdk.internal.event.Example"})
+ *
+ * @return the fully qualified class name of the event
+ */
+ String className();
+
+ /**
+ * The module where the event is located, by default {@code "java.base"}.
+ *
+ * @return the module name
+ */
+ String module() default "java.base";
+}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java Wed Oct 31 02:10:21 2018 +0100
@@ -81,9 +81,7 @@
Logger.log(JFR_SYSTEM, INFO, "Registered JDK events");
JDKEvents.addInstrumentation();
startDiskMonitor();
- SecuritySupport.registerEvent(ActiveRecordingEvent.class);
activeRecordingEvent = EventType.getEventType(ActiveRecordingEvent.class);
- SecuritySupport.registerEvent(ActiveSettingEvent.class);
activeSettingEvent = EventType.getEventType(ActiveSettingEvent.class);
shutdownHook = SecuritySupport.createThreadWitNoPermissions("JFR: Shutdown Hook", new ShutdownHook(this));
SecuritySupport.setUncaughtExceptionHandler(shutdownHook, new ShutdownHook.ExceptionHandler());
@@ -91,6 +89,7 @@
timer = createTimer();
}
+
private static Timer createTimer() {
try {
List<Timer> result = new CopyOnWriteArrayList<>();
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java Wed Oct 31 02:10:21 2018 +0100
@@ -262,8 +262,12 @@
Modules.addExports(JFR_MODULE, Utils.HANDLERS_PACKAGE_NAME, clazz.getModule());
}
- public static void registerEvent(Class<? extends Event> eventClass) {
- doPrivileged(() -> FlightRecorder.register(eventClass), new FlightRecorderPermission(Utils.REGISTER_EVENT));
+ public static void registerEvent(Class<? extends jdk.internal.event.Event> eventClass) {
+ doPrivileged(() -> MetadataRepository.getInstance().register(eventClass), new FlightRecorderPermission(Utils.REGISTER_EVENT));
+ }
+
+ public static void registerMirror(Class<? extends Event> eventClass) {
+ doPrivileged(() -> MetadataRepository.getInstance().registerMirror(eventClass), new FlightRecorderPermission(Utils.REGISTER_EVENT));
}
static boolean getBooleanProperty(String propertyName) {
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java Wed Oct 31 02:10:21 2018 +0100
@@ -37,7 +37,6 @@
import java.util.Set;
import java.util.StringJoiner;
-import jdk.jfr.Event;
import jdk.jfr.internal.handlers.EventHandler;
final class SettingsManager {
@@ -152,9 +151,9 @@
}
}
- public void updateRetransform(List<Class<? extends Event>> eventClasses) {
+ public void updateRetransform(List<Class<? extends jdk.internal.event.Event>> eventClasses) {
List<Class<?>> classes = new ArrayList<>();
- for(Class<? extends Event> eventClass: eventClasses) {
+ for(Class<? extends jdk.internal.event.Event> eventClass: eventClasses) {
EventHandler eh = Utils.getHandler(eventClass);
if (eh != null ) {
PlatformEventType eventType = eh.getPlatformEventType();
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java Wed Oct 31 02:10:21 2018 +0100
@@ -71,10 +71,11 @@
private final String name;
private final String superType;
private final boolean constantPool;
- private final long id;
private final ArrayList<ValueDescriptor> fields = new ArrayList<>();
private Boolean simpleType; // calculated lazy
private boolean remove = true;
+ private long id;
+
/**
* Creates a type
*
@@ -318,4 +319,8 @@
public boolean getRemove() {
return remove;
}
+
+ public void setId(long id) {
+ this.id = id;
+ }
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java Wed Oct 31 02:10:21 2018 +0100
@@ -49,7 +49,6 @@
import jdk.jfr.AnnotationElement;
import jdk.jfr.Description;
-import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.MetadataDefinition;
import jdk.jfr.Name;
@@ -240,7 +239,7 @@
// STRUCT
String superType = null;
boolean eventType = false;
- if (Event.class.isAssignableFrom(clazz)) {
+ if (jdk.internal.event.Event.class.isAssignableFrom(clazz)) {
superType = Type.SUPER_TYPE_EVENT;
eventType= true;
}
@@ -489,4 +488,8 @@
aQ.addAll(ae.getAnnotationElements());
}
}
+
+ public void removeType(long id) {
+ types.remove(id);
+ }
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Wed Oct 31 02:10:21 2018 +0100
@@ -267,7 +267,7 @@
return (long) (nanos * JVM.getJVM().getTimeConversionFactor());
}
- static synchronized EventHandler getHandler(Class<? extends Event> eventClass) {
+ static synchronized EventHandler getHandler(Class<? extends jdk.internal.event.Event> eventClass) {
Utils.ensureValidEventSubclass(eventClass);
try {
Field f = eventClass.getDeclaredField(EventInstrumentation.FIELD_EVENT_HANDLER);
@@ -278,7 +278,7 @@
}
}
- static synchronized void setHandler(Class<? extends Event> eventClass, EventHandler 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);
@@ -322,7 +322,7 @@
static List<Field> getVisibleEventFields(Class<?> clazz) {
Utils.ensureValidEventSubclass(clazz);
List<Field> fields = new ArrayList<>();
- for (Class<?> c = clazz; c != Event.class; c = c.getSuperclass()) {
+ for (Class<?> c = clazz; c != jdk.internal.event.Event.class; c = c.getSuperclass()) {
for (Field field : c.getDeclaredFields()) {
// skip private field in base classes
if (c == clazz || !Modifier.isPrivate(field.getModifiers())) {
@@ -334,10 +334,10 @@
}
public static void ensureValidEventSubclass(Class<?> eventClass) {
- if (Event.class.isAssignableFrom(eventClass) && Modifier.isAbstract(eventClass.getModifiers())) {
+ if (jdk.internal.event.Event.class.isAssignableFrom(eventClass) && Modifier.isAbstract(eventClass.getModifiers())) {
throw new IllegalArgumentException("Abstract event classes are not allowed");
}
- if (eventClass == Event.class || !Event.class.isAssignableFrom(eventClass)) {
+ if (eventClass == Event.class || eventClass == jdk.internal.event.Event.class || !jdk.internal.event.Event.class.isAssignableFrom(eventClass)) {
throw new IllegalArgumentException("Must be a subclass to " + Event.class.getName());
}
}
@@ -366,7 +366,7 @@
}
}
- public static void ensureInitialized(Class<? extends Event> eventClass) {
+ public static void ensureInitialized(Class<? extends jdk.internal.event.Event> eventClass) {
SecuritySupport.ensureClassIsInitialized(eventClass);
}
@@ -499,6 +499,50 @@
return eventName;
}
+ public static void verifyMirror(Class<?> mirror, Class<?> real) {
+ Class<?> cMirror = Objects.requireNonNull(mirror);
+ Class<?> cReal = Objects.requireNonNull(real);
+
+ while (cReal != null) {
+ Map<String, Field> mirrorFields = new HashMap<>();
+ if (cMirror != null) {
+ for (Field f : cMirror.getDeclaredFields()) {
+ if (isSupportedType(f.getType())) {
+ mirrorFields.put(f.getName(), f);
+ }
+ }
+ }
+ for (Field realField : cReal.getDeclaredFields()) {
+ if (isSupportedType(realField.getType())) {
+ String fieldName = realField.getName();
+ Field mirrorField = mirrorFields.get(fieldName);
+ if (mirrorField == null) {
+ throw new InternalError("Missing mirror field for " + cReal.getName() + "#" + fieldName);
+ }
+ if (realField.getModifiers() != mirrorField.getModifiers()) {
+ throw new InternalError("Incorrect modifier for mirror field "+ cMirror.getName() + "#" + fieldName);
+ }
+ mirrorFields.remove(fieldName);
+ }
+ }
+ if (!mirrorFields.isEmpty()) {
+ throw new InternalError(
+ "Found additional fields in mirror class " + cMirror.getName() + " " + mirrorFields.keySet());
+ }
+ if (cMirror != null) {
+ cMirror = cMirror.getSuperclass();
+ }
+ cReal = cReal.getSuperclass();
+ }
+ }
+
+ private static boolean isSupportedType(Class<?> type) {
+ if (Modifier.isTransient(type.getModifiers()) || Modifier.isStatic(type.getModifiers())) {
+ return false;
+ }
+ return Type.isValidJavaFieldType(type.getName());
+ }
+
public static String makeFilename(Recording recording) {
String pid = JVM.getJVM().getPid();
String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now());
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Tue Oct 30 15:17:58 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java Wed Oct 31 02:10:21 2018 +0100
@@ -51,6 +51,9 @@
public final class JDKEvents {
+ private static final Class<?>[] mirrorEventClasses = {
+ };
+
private static final Class<?>[] eventClasses = {
FileForceEvent.class,
FileReadEvent.class,
@@ -90,6 +93,9 @@
Modules.addExports(jdkJfrModule, Utils.EVENTS_PACKAGE_NAME, javaBaseModule);
Modules.addExports(jdkJfrModule, Utils.INSTRUMENT_PACKAGE_NAME, javaBaseModule);
Modules.addExports(jdkJfrModule, Utils.HANDLERS_PACKAGE_NAME, javaBaseModule);
+ for (Class<?> mirrorEventClass : mirrorEventClasses) {
+ SecuritySupport.registerMirror(((Class<? extends Event>)mirrorEventClass));
+ }
for (Class<?> eventClass : eventClasses) {
SecuritySupport.registerEvent((Class<? extends Event>) eventClass);
}
--- a/test/jdk/jdk/jfr/jvm/TestGetAllEventClasses.java Tue Oct 30 15:17:58 2018 -0700
+++ b/test/jdk/jdk/jfr/jvm/TestGetAllEventClasses.java Wed Oct 31 02:10:21 2018 +0100
@@ -104,8 +104,9 @@
}
@SafeVarargs
+ @SuppressWarnings("rawtypes")
private static void assertEvents(JVM jvm, boolean inclusion, Class<? extends Event>... targetEvents) {
- final List<Class<? extends Event>> list = jvm.getAllEventClasses();
+ final List list = jvm.getAllEventClasses();
for (Class<? extends Event> ev : targetEvents) {
if (list.contains(ev)) {
if (inclusion) {