/* * Copyright (c) 2022, 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.
*/
publicstaticvoid main(String... args) throws Throwable { try (Recording r = new Recording()) {
r.start(); // Unlocks access to jdk.jfr.internal.event
InitializationEvent e = new InitializationEvent();
e.commit();
} // Make sure EventWriterFactory can be accessed. Class<?> clazz = Class.forName("jdk.jfr.internal.event.EventWriterFactory"); if (clazz == null) { thrownew Exception("Test error, not able to access jdk.jfr.internal.event.EventWriterFactory class");
}
testRegisteredTrueEvent();
testRegisteredFalseEvent();
testMyCommitRegisteredTrue();
testMyCommitRegisteredFalse();
testStaticCommit();
testMethodHandleEvent();
testReflectionEvent();
testNonEvent();
}
// The class does not inherit jdk.jfr.Event and, as such, does not implement the // API. It has its own stand-alone "commit()V", which is not an override, that // attempts to resolve and link against EventWriterFactory. This user implementation // is not blessed for linkage. privatestaticvoid testNonEvent() throws Throwable {
Runnable e = newEventObject("NonEvent"); try {
e.run(); // invokes commit() thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "commit"); return;
}
}
// The user has defined a class which overrides and implements the "commit()V" // method declared final in jdk.jfr.Event. // This user implementation is not blessed for linkage. privatestaticvoid testRegisteredTrueEvent() throws Throwable {
Event e = newEventObject("RegisteredTrueEvent"); try {
e.commit(); // throws thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "commit"); return;
}
}
// The user has defined a class which overrides and implements the "commit()V" // method declared final in jdk.jfr.Event. This user implementation is not // blessed for linkage. If a class have user-defined implementations // of any methods declared final, it is not instrumented. // Although it is a subclass of jdk.jfr.Event, on initial load, we will // classify it as being outside of the JFR system. Attempting to register // such a class throws an IllegalArgumentException. The user-defined // "commit()V" method is still not blessed for linkage, even after registration. privatestaticvoid testRegisteredFalseEvent() throws Throwable {
Event e = newEventObject("RegisteredFalseEvent"); try {
e.commit(); // throws thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "commit");
} try {
FlightRecorder.register(e.getClass());
} catch (IllegalArgumentException iae) { // OK, as expected. // Can't register an event class where the user has managed to override // methods in jdk.jfr.Event
}
}
// The user has implemented another method, "myCommit()V", not an override nor // overload. that attempts to resolve and link EventWriterFactory. This will fail, // because "myCommit()V" is not blessed for linkage. privatestaticvoid testMyCommitRegisteredTrue() throws Throwable {
Runnable e = newEventObject("MyCommitRegisteredTrueEvent"); try {
e.run(); // Invoking the user-defined method throws. thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "myCommit"); return;
}
}
// The user has implemented another method, "myCommit()V", not an override, // nor overload. This linkage will fail because "myCommit()V" is not blessed. // Since the user has not defined any final methods in jdk.jfr.Event, // the class is not excluded wholesale from the JFR system. // Invoking the real "commit()V", installed by the framework, is OK. privatestaticvoid testMyCommitRegisteredFalse() throws Throwable {
Runnable e = newEventObject("MyCommitRegisteredFalseEvent"); try {
e.run(); // Invoking the user-defined method throws. thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "myCommit");
} // Instrumentation added.
FlightRecorder.register(e.getClass().asSubclass(Event.class));
Event event = (Event) e;
event.commit(); // Invoking the JFR provided method is OK
}
// Events located in the boot class loader can create a static // commit-method to emit events. It must not be used by code // outside of the boot class loader. privatestaticvoid testStaticCommit() throws Throwable {
Runnable e = newEventObject("StaticCommitEvent"); try {
e.run(); // Invokes commit(long, long, String, int) thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessError iae) { // OK, as expected
maybeCheckJVMCI(e.getClass(), "commit");
}
}
// The user has implemented another method, "myCommit()V", not an override, // nor overload. This linkage will fail, because "myCommit()V" is not blessed. // Using a MethodHandle for linkage is transparent and immaterial. privatestaticvoid testMethodHandleEvent() throws Throwable {
MethodHandleEvent e = new MethodHandleEvent(); try {
e.myCommit(); thrownew RuntimeException("Should not reach here");
} catch (IllegalAccessException iaex) { if (iaex.getCause() instanceof IllegalAccessError iae) { if (iae.getMessage().contains("getEventWriter(long)")) { // OK, as expected return;
}
}
}
}
// The user has implemented another method, "myCommit()V", not an override, // nor overload, that uses Reflection. This linkage will fail, because // "myCommit()V" is not blessed. Reflection is using method handles, // but using a MethodHandle for linkage is transparent and immaterial. privatestaticvoid testReflectionEvent() throws Throwable {
ReflectionEvent e = new ReflectionEvent(); try {
e.myCommit(); // throws thrownew RuntimeException("Should not reach here");
} catch (InternalError ie) { if (ie.getCause() instanceof IllegalAccessException iaex) { if (iaex.getCause() instanceof IllegalAccessError iae) { if (iae.getMessage().contains("getEventWriter(long)")) { // OK, as expected return;
}
}
}
}
}
privatestaticbyte[] replace(byte[] bytes, String match, String replacement) { if (match.length() != replacement.length()) { thrownew IllegalArgumentException("Match must be same size as replacement");
} for (int i = 0; i < bytes.length - match.length(); i++) { if (match(bytes, i, match)) { for (int j = 0; j < replacement.length(); j++) {
bytes[i + j] = (byte) replacement.charAt(j);
}
}
} return bytes;
}
privatestaticboolean match(byte[] bytes, int offset, String text) { for (int i = 0; i < text.length(); i++) { if (bytes[offset + i] != text.charAt(i)) { returnfalse;
}
} returntrue;
}
@SuppressWarnings("unchecked") privatestatic <T> T newEventObject(String name) throws Throwable {
String r = name + ".class";
String fullName = "jdk.jfr.jvm." + name; var is = TestGetEventWriter.class.getResourceAsStream(r); if (is == null) { thrownew Exception("Test error, could not located class file for " + name);
} byte[] bytes = is.readAllBytes();
is.close();
bytes = replace(bytes, "jdk/jfr/jvm/E", "jdk/jfr/Event");
bytes = replace(bytes, "jdk/jfr/jvm/PlaceholderEventWriterFactory", "jdk/jfr/internal/event/EventWriterFactory");
bytes = replace(bytes, "jdk/jfr/jvm/PlaceholderEventWriter", "jdk/jfr/internal/event/EventWriter");
BytesClassLoader bc = new BytesClassLoader(bytes, fullName); Class<?> clazz = bc.loadClass(fullName);
Constructor<?> constructor = clazz.getConstructor(newClass[0]);
System.out.println("About to invoke " + fullName + ".commit()"); return (T) constructor.newInstance();
}
privatestatic ResolvedJavaMethod findCommitMethod(MetaAccessProvider metaAccess, Class<?> eventClass, String commitName) { for (Method m : eventClass.getMethods()) { if (m.getName().equals(commitName)) { return metaAccess.lookupJavaMethod(m);
}
} thrownew AssertionError("could not find " + commitName + " method in " + eventClass);
}
// Factor out test.jvmci system property check to reduce unecessary work in -Xcomp. privatestaticvoid maybeCheckJVMCI(Class<?> eventClass, String commitName) throws Throwable { if (!Boolean.getBoolean("test.jvmci")) { return;
}
checkJVMCI(eventClass, commitName);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.