|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package jdk.jfr.internal; |
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
import jdk.jfr.Event; |
|
import jdk.jfr.internal.handlers.EventHandler; |
|
import jdk.jfr.internal.instrument.JDKEvents; |
|
|
|
/** |
|
* All upcalls from the JVM should go through this class. |
|
* |
|
*/ |
|
|
|
final class JVMUpcalls { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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 (handler == null) { |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "No event handler found for " + clazz.getName() + ". Ignoring instrumentation request."); |
|
|
|
return oldBytes; |
|
} |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding instrumentation to event class " + clazz.getName() + " using retransform"); |
|
EventInstrumentation ei = new EventInstrumentation(clazz.getSuperclass(), oldBytes, traceId); |
|
byte[] bytes = ei.buildInstrumented(); |
|
ASMToolkit.logASM(clazz.getName(), bytes); |
|
return bytes; |
|
} |
|
return JDKEvents.retransformCallback(clazz, oldBytes); |
|
} catch (Throwable t) { |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Unexpected error when adding instrumentation to event class " + clazz.getName()); |
|
} |
|
return oldBytes; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static byte[] bytesForEagerInstrumentation(long traceId, boolean forceInstrumentation, Class<?> superClass, byte[] oldBytes) throws Throwable { |
|
if (JVMSupport.isNotAvailable()) { |
|
return oldBytes; |
|
} |
|
String eventName = "<Unknown>"; |
|
try { |
|
EventInstrumentation ei = new EventInstrumentation(superClass, oldBytes, traceId); |
|
eventName = ei.getEventName(); |
|
if (!forceInstrumentation) { |
|
|
|
MetadataRepository mr = MetadataRepository.getInstance(); |
|
// No need to generate bytecode if: |
|
// 1) Event class is disabled, and there is not an external configuration that overrides. |
|
|
|
if (!mr.isEnabled(ei.getEventName()) && !ei.isEnabled() || !ei.isRegistered()) { |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Skipping instrumentation for event type " + eventName + " since event was disabled on class load"); |
|
return oldBytes; |
|
} |
|
} |
|
// Corner case when we are forced to generate bytecode. We can't reference the event |
|
// handler in #isEnabled() before event class has been registered, so we add a |
|
|
|
ei.setGuardHandler(true); |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding " + (forceInstrumentation ? "forced " : "") + "instrumentation for event type " + eventName + " during initial class load"); |
|
EventHandlerCreator eh = new EventHandlerCreator(traceId, ei.getSettingInfos(), ei.getFieldInfos()); |
|
// Handler class must be loaded before instrumented event class can |
|
|
|
eh.makeEventHandlerClass(); |
|
byte[] bytes = ei.buildInstrumented(); |
|
ASMToolkit.logASM(ei.getClassName() + "(" + traceId + ")", bytes); |
|
return bytes; |
|
} catch (Throwable t) { |
|
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Unexpected error when adding instrumentation for event type " + eventName); |
|
return oldBytes; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static Thread createRecorderThread(ThreadGroup systemThreadGroup, ClassLoader contextClassLoader) { |
|
return SecuritySupport.createRecorderThread(systemThreadGroup, contextClassLoader); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static Class<? extends EventHandler> getEventHandlerProxyClass() { |
|
return EventHandlerProxyCreator.proxyClass; |
|
} |
|
} |