All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.lib.profiler.client.RuntimeProfilingPoint Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.lib.profiler.client;

import org.netbeans.lib.profiler.classfile.ClassInfo;
import org.netbeans.lib.profiler.classfile.ClassRepository;


/**
 * Represents a Profiling point.
 * Its lifetime must not span across sessions.
 *
 * @author Tomas Hurka
 * @author Maros Sandor
 */
public class RuntimeProfilingPoint implements Comparable {
    //~ Inner Classes ------------------------------------------------------------------------------------------------------------

    /**
     * Encapsulates an event of hitting a profiling point.
     */
    public static class HitEvent {
        //~ Instance fields ------------------------------------------------------------------------------------------------------

        private final int id;
        private final int threadId;
        private final long timestamp;

        //~ Constructors ---------------------------------------------------------------------------------------------------------

        public HitEvent(int id, long timestamp, int threadId) {
            this.id = id;
            this.timestamp = timestamp;
            this.threadId = threadId;
        }

        //~ Methods --------------------------------------------------------------------------------------------------------------

        public int getId() {
            return id;
        }

        public int getThreadId() {
            return threadId;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public String toString() {
            return "HitEvent [id=" + getId() + ", thread id=" + getThreadId() + ", timestamp=" + getTimestamp() + "]"; //NOI18N
        }
    }

    //~ Instance fields ----------------------------------------------------------------------------------------------------------

    /**
     * Name of the class where the profiling point resides in the form: package.Class.Inner
     */
    private final String className;

    /**
     * Name of the method where this profiling point resides. This is mutually exclusive with the line field and means
     * "beginning of a method".
     */
    private final String methodName;

    /**
     * Signature of the method where this profiling point resides. This is mutually exclusive with the line field and
     * supplements the methodName field. May be null to indicate 'the first method with the given name'.
     */
    private final String methodSignature;

    /**
     * Handler for hit events.
     */
    private final String serverHandlerClass;

    /**
     * Additional arbitrary info send to server
     */
    private final String serverInfo;

    /**
     * ID identifies this profiling point in eventbuffer events.
     */
    private final int id;

    /**
     * Line number where this profiling point resides. This is mutually exclusive with the method field.
     */
    private final int line;

    /**
     * Line offset where this profiling point resides. This is mutually exclusive with the method field.
     */
    private final int offset;

    /**
     * Bytecode index; filled at runtime when the class loads and we inject profile point hit methods.
     */
    private int bci;

    /**
     * Method index; filled at runtime when the class loads and we inject profile point hit methods.
     */
    private int methodIdx = -1;

    //~ Constructors -------------------------------------------------------------------------------------------------------------

    /**
     * Creates a new profiling point.
     *
     *
     *
     * @param id unique ID of this profiling point
     * @param className name of the class where this profiling point is placed
     * @param line profiling point location in the class. If line is positive, it is be inserted just before the line executes.
     *             If line is negative, it is inserted just after the line executes.
     * @param offset line offset
     * @param serverHandlerClass handles hits of this profiling point on server side (fully qualified class name)
     */
    public RuntimeProfilingPoint(int id, String className, int line, int offset, String serverHandlerClass, String serverInfo) {
        this(id, className, line, offset, null, null, serverHandlerClass, serverInfo);
    }

    /**
     * Creates a new profiling point.
     *
     *
     *
     * @param id unique ID of this profiling point
     * @param className name of the class where this profiling point is placed
     * @param methodName name of the method where this profiling point is placed
     * @param methodSignature signature of the method where this profiling point is placed
     * @param serverHandlerClass handles hits of this profiling point on server side (fully qualified class name)
     */
    public RuntimeProfilingPoint(int id, String className, String methodName, String methodSignature, String serverHandlerClass,
                                 String serverInfo) {
        this(id, className, -1, -1, methodName, methodSignature, serverHandlerClass, serverInfo);
    }

    private RuntimeProfilingPoint(int id, String className, int line, int offset, String methodName, String methodSignature,
                                  String serverHandlerClass, String serverInfo) {
        this.id = id;
        this.className = className;
        this.line = line;
        this.offset = offset;
        this.methodName = methodName;
        this.methodSignature = methodSignature;
        this.serverHandlerClass = serverHandlerClass;
        this.serverInfo = serverInfo;
    }

    //~ Methods ------------------------------------------------------------------------------------------------------------------

    public int getBci() {
        return bci;
    }

    public String getClassName() {
        return className;
    }

    public int getId() {
        return id;
    }

    public int getMethodIdx() {
        return methodIdx;
    }

    public String getServerHandlerClass() {
        return serverHandlerClass;
    }

    public String getServerInfo() {
        return serverInfo;
    }

    public boolean resolve(ClassInfo classInfo) {
        if (methodIdx != -1) {
            return true;
        }

        return (methodName != null) ? resolveMethodName(classInfo) : resolveLineNumber(classInfo);
    }

    public String toString() {
        return "RuntimeProfilingPoint [id=" + id + ", classname=" + className + ", line=" + line + ", offset=" + offset
               + ", server handler=" + serverHandlerClass + "]"; //NOI18N
    }

    public int compareTo(Object o) {
        if (!(o instanceof RuntimeProfilingPoint)) return -1;
        if (o == null) return -1;
        return getId() - ((RuntimeProfilingPoint)o).getId();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final RuntimeProfilingPoint other = (RuntimeProfilingPoint) obj;
        if (this.id != other.id) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 23 * hash + this.id;
        return hash;
    }

    private boolean resolveLineNumber(ClassInfo classInfo) {
        try {
            //      int ln = Math.abs(line);
            ClassRepository.CodeRegionBCI crbci = ClassRepository.getMethodForSourceRegion(classInfo, line, line);
            methodIdx = classInfo.getMethodIndex(crbci.methodName, crbci.methodSignature);
            bci = (offset == Integer.MAX_VALUE) ? crbci.bci1 : crbci.bci0;

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private boolean resolveMethodName(ClassInfo classInfo) {
        if (methodSignature != null) {
            methodIdx = classInfo.getMethodIndex(methodName, methodSignature);
        } else {
            String[] allNames = classInfo.getMethodNames();

            for (int i = 0; i < allNames.length; i++) {
                if (methodName.equals(allNames[i])) {
                    methodIdx = i;

                    break;
                }
            }
        }

        if (methodIdx == -1) {
            return false;
        }

        bci = classInfo.getLineNumberTables().getStartPCs()[methodIdx][0];

        return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy