|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package jdk.jfr.internal; |
|
|
|
import java.util.StringJoiner; |
|
|
|
import jdk.internal.org.objectweb.asm.ClassWriter; |
|
import jdk.internal.org.objectweb.asm.MethodVisitor; |
|
import jdk.internal.org.objectweb.asm.Opcodes; |
|
import jdk.internal.org.objectweb.asm.Type; |
|
import jdk.internal.org.objectweb.asm.commons.Method; |
|
import jdk.jfr.Event; |
|
import jdk.jfr.EventType; |
|
import jdk.jfr.internal.handlers.EventHandler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
final class EventHandlerProxyCreator { |
|
private static final int CLASS_VERSION = 52; |
|
|
|
private final static Type TYPE_EVENT_TYPE = Type.getType(EventType.class); |
|
private final static Type TYPE_EVENT_CONTROL = Type.getType(EventControl.class); |
|
private final static String DESCRIPTOR_EVENT_HANDLER = "(" + Type.BOOLEAN_TYPE.getDescriptor() + TYPE_EVENT_TYPE.getDescriptor() + TYPE_EVENT_CONTROL.getDescriptor() + ")V"; |
|
private final static Method METHOD_EVENT_HANDLER_CONSTRUCTOR = new Method("<init>", DESCRIPTOR_EVENT_HANDLER); |
|
private final static String DESCRIPTOR_TIME_STAMP = "()" + Type.LONG_TYPE.getDescriptor(); |
|
private final static Method METHOD_TIME_STAMP = new Method("timestamp", DESCRIPTOR_TIME_STAMP); |
|
private final static String DESCRIPTOR_DURATION = "(" + Type.LONG_TYPE.getDescriptor() + ")" + Type.LONG_TYPE.getDescriptor(); |
|
private final static Method METHOD_DURATION = new Method("duration", DESCRIPTOR_DURATION); |
|
|
|
private final static ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); |
|
private final static String className = "jdk.jfr.proxy.internal.EventHandlerProxy"; |
|
private final static String internalClassName = ASMToolkit.getInternalName(className); |
|
|
|
|
|
static final Class<? extends EventHandler> proxyClass = EventHandlerProxyCreator.makeEventHandlerProxyClass(); |
|
|
|
static void ensureInitialized() { |
|
// trigger clinit which will setup the EventHandlerProxy class. |
|
} |
|
|
|
public static Class<? extends EventHandler> makeEventHandlerProxyClass() { |
|
buildClassInfo(); |
|
buildConstructor(); |
|
buildTimestampMethod(); |
|
buildDurationMethod(); |
|
byte[] bytes = classWriter.toByteArray(); |
|
ASMToolkit.logASM(className, bytes); |
|
return SecuritySupport.defineClass(className, bytes, Event.class.getClassLoader()).asSubclass(EventHandler.class); |
|
} |
|
|
|
private static void buildConstructor() { |
|
MethodVisitor mv = classWriter.visitMethod(0x0, METHOD_EVENT_HANDLER_CONSTRUCTOR.getName(), makeConstructorDescriptor(), null, null); |
|
mv.visitVarInsn(Opcodes.ALOAD, 0); |
|
mv.visitVarInsn(Opcodes.ILOAD, 1); |
|
mv.visitVarInsn(Opcodes.ALOAD, 2); |
|
mv.visitVarInsn(Opcodes.ALOAD, 3); |
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(EventHandler.class), METHOD_EVENT_HANDLER_CONSTRUCTOR.getName(), METHOD_EVENT_HANDLER_CONSTRUCTOR.getDescriptor(), false); |
|
mv.visitInsn(Opcodes.RETURN); |
|
mv.visitMaxs(0, 0); |
|
mv.visitEnd(); |
|
} |
|
|
|
private static void buildClassInfo() { |
|
String internalSuperName = ASMToolkit.getInternalName(EventHandler.class.getName()); |
|
classWriter.visit(CLASS_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SUPER, internalClassName, null, internalSuperName, null); |
|
} |
|
|
|
private static void buildTimestampMethod() { |
|
MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, METHOD_TIME_STAMP.getName(), METHOD_TIME_STAMP.getDescriptor(), null, null); |
|
mv.visitCode(); |
|
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(EventHandler.class), METHOD_TIME_STAMP.getName(), METHOD_TIME_STAMP.getDescriptor(), false); |
|
mv.visitInsn(Opcodes.LRETURN); |
|
mv.visitMaxs(0, 0); |
|
mv.visitEnd(); |
|
} |
|
|
|
private static void buildDurationMethod() { |
|
MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, METHOD_DURATION.getName(), METHOD_DURATION.getDescriptor(), null, null); |
|
mv.visitCode(); |
|
mv.visitVarInsn(Opcodes.LLOAD, 0); |
|
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(EventHandler.class), METHOD_DURATION.getName(), METHOD_DURATION.getDescriptor(), false); |
|
mv.visitInsn(Opcodes.LRETURN); |
|
mv.visitMaxs(0, 0); |
|
mv.visitEnd(); |
|
} |
|
|
|
private static String makeConstructorDescriptor() { |
|
StringJoiner constructordescriptor = new StringJoiner("", "(", ")V"); |
|
constructordescriptor.add(Type.BOOLEAN_TYPE.getDescriptor()); |
|
constructordescriptor.add(Type.getType(EventType.class).getDescriptor()); |
|
constructordescriptor.add(Type.getType(EventControl.class).getDescriptor()); |
|
return constructordescriptor.toString(); |
|
} |
|
} |