src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java
author egahlin
Tue, 15 May 2018 20:24:34 +0200
changeset 50113 caf115bb98ad
child 52015 821bfc24d750
permissions -rw-r--r--
8199712: Flight Recorder Reviewed-by: coleenp, ihse, erikj, dsamersoff, mseledtsov, egahlin, mgronlun Contributed-by: erik.gahlin@oracle.com, markus.gronlund@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     2
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     4
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    10
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    15
 * accompanied this code).
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    16
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    20
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    23
 * questions.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    24
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    25
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    26
package jdk.jfr.internal;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    27
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    28
import java.util.List;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    29
import java.util.concurrent.atomic.AtomicLong;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    30
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    31
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    32
import jdk.internal.org.objectweb.asm.ClassWriter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    33
import jdk.internal.org.objectweb.asm.Label;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    34
import jdk.internal.org.objectweb.asm.MethodVisitor;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    35
import jdk.internal.org.objectweb.asm.Opcodes;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
import jdk.internal.org.objectweb.asm.Type;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    37
import jdk.internal.org.objectweb.asm.commons.GeneratorAdapter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
import jdk.internal.org.objectweb.asm.commons.Method;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
import jdk.jfr.AnnotationElement;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
import jdk.jfr.Event;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
import jdk.jfr.ValueDescriptor;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
// Helper class for building dynamic events
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
public final class EventClassBuilder {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
    private static final Type TYPE_EVENT = Type.getType(Event.class);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
    private static final Type TYPE_IOBE = Type.getType(IndexOutOfBoundsException.class);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
    private static final Method DEFAULT_CONSTRUCTOR = Method.getMethod("void <init> ()");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
    private static final Method SET_METHOD = Method.getMethod("void set (int, java.lang.Object)");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
    private static final AtomicLong idCounter = new AtomicLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
    private final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
    private final String fullClassName;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
    private final Type type;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
    private final List<ValueDescriptor> fields;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
    private final List<AnnotationElement> annotationElements;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    57
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    58
    public EventClassBuilder(List<AnnotationElement> annotationElements, List<ValueDescriptor> fields) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    59
        this.fullClassName = "jdk.jfr.DynamicEvent" + idCounter.incrementAndGet();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    60
        this.type = Type.getType(fullClassName.replace(".", "/"));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    61
        this.fields = fields;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    62
        this.annotationElements = annotationElements;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    63
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    64
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
    public Class<? extends Event> build() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
        buildClassInfo();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    67
        buildConstructor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    68
        buildFields();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    69
        buildSetMethod();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    70
        endClass();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    71
        byte[] bytes = classWriter.toByteArray();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    72
        ASMToolkit.logASM(fullClassName, bytes);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    73
        return SecuritySupport.defineClass(type.getInternalName(), bytes, Event.class.getClassLoader()).asSubclass(Event.class);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    74
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    75
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    76
    private void endClass() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    77
        classWriter.visitEnd();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    78
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    79
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    80
    private void buildSetMethod() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    81
        GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC, SET_METHOD, null, null, classWriter);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    82
        int index = 0;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    83
        for (ValueDescriptor v : fields) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    84
            ga.loadArg(0);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    85
            ga.visitLdcInsn(index);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    86
            Label notEqual = new Label();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    87
            ga.ifICmp(GeneratorAdapter.NE, notEqual);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    88
            ga.loadThis();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    89
            ga.loadArg(1);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    90
            Type fieldType = ASMToolkit.toType(v);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    91
            ga.unbox(ASMToolkit.toType(v));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    92
            ga.putField(type, v.getName(), fieldType);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    93
            ga.visitInsn(Opcodes.RETURN);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    94
            ga.visitLabel(notEqual);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    95
            index++;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    96
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    97
        ga.throwException(TYPE_IOBE, "Index must between 0 and " + fields.size());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    98
        ga.endMethod();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    99
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   100
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   101
    private void buildConstructor() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   102
        MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, DEFAULT_CONSTRUCTOR.getName(), DEFAULT_CONSTRUCTOR.getDescriptor(), null, null);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   103
        mv.visitIntInsn(Opcodes.ALOAD, 0);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   104
        ASMToolkit.invokeSpecial(mv, TYPE_EVENT.getInternalName(), DEFAULT_CONSTRUCTOR);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   105
        mv.visitInsn(Opcodes.RETURN);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   106
        mv.visitMaxs(0, 0);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   107
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   108
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   109
    private void buildClassInfo() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   110
        String internalSuperName = ASMToolkit.getInternalName(Event.class.getName());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   111
        String internalClassName = type.getInternalName();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   112
        classWriter.visit(52, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, internalClassName, null, internalSuperName, null);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   114
        for (AnnotationElement a : annotationElements) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   115
            String descriptor = ASMToolkit.getDescriptor(a.getTypeName());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   116
            AnnotationVisitor av = classWriter.visitAnnotation(descriptor, true);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   117
            for (ValueDescriptor v : a.getValueDescriptors()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   118
                Object value = a.getValue(v.getName());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   119
                String name = v.getName();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   120
                if (v.isArray()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   121
                    AnnotationVisitor arrayVisitor = av.visitArray(name);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   122
                    Object[] array = (Object[]) value;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   123
                    for (int i = 0; i < array.length; i++) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   124
                        arrayVisitor.visit(null, array[i]);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   125
                    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   126
                    arrayVisitor.visitEnd();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   127
                } else {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   128
                    av.visit(name, value);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   129
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   130
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   131
            av.visitEnd();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   132
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   133
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   134
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   135
    private void buildFields() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   136
        for (ValueDescriptor v : fields) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   137
            String internal = ASMToolkit.getDescriptor(v.getTypeName());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   138
            classWriter.visitField(Opcodes.ACC_PRIVATE, v.getName(), internal, null, null);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   139
            // No need to store annotations on field since they will be replaced anyway.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   140
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   141
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   142
}