instrumentj.impl.InstrumentMethodVisitor.java Source code

Java tutorial

Introduction

Here is the source code for instrumentj.impl.InstrumentMethodVisitor.java

Source

/*
 * Licensed 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 instrumentj.impl;

import instrumentj.Constants;
import instrumentj.StaticProfilerInterface;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AdviceAdapter;

/**
 * @author Stephen Evanchik (evanchsa@gmail.com)
 *
 */
public class InstrumentMethodVisitor extends AdviceAdapter implements Constants {

    private final String className;

    private final String methodName;

    private final String methodDescription;

    /**
     *
     * @param className
     * @param mv
     * @param access
     * @param methodName
     * @param methodDescription
     */
    public InstrumentMethodVisitor(final String className, final MethodVisitor mv, final int access,
            final String methodName, final String methodDescription) {
        super(Opcodes.ASM4, mv, access, methodName, methodDescription);

        if (className == null) {
            throw new NullPointerException("className");
        }

        if (methodName == null) {
            throw new NullPointerException("methodName");
        }

        this.className = className;
        this.methodName = methodName;
        this.methodDescription = methodDescription;
    }

    /**
     * Adds a call to
     * {@link StaticProfilerInterface#objectAllocationProbes(String)} in the
     * case of constructor calls and also a call to
     * {@link StaticProfilerInterface#methodEnterProbes(String, String)}
     * <br>
     * <br>
     * {@inheritDoc}
     */
    @Override
    protected void onMethodEnter() {
        final boolean constructor = "<init>".equals(methodName);
        if (constructor) {
            visitLdcInsn(className);

            visitMethodInsn(INVOKESTATIC, INSTRUMENTJ_STATIC_PROFILER_INTERFACE, OBJECT_ALLOCATION_PROBES,
                    OBJECT_ALLOCATION_PROBES_DESC);
        }

        visitLdcInsn(className);
        visitLdcInsn(methodName);
        visitLdcInsn(methodDescription);

        final Type[] argTypes = Type.getArgumentTypes(methodDescription);
        final int argCount = argTypes.length;

        if (argCount > 0) {
            loadArgArray();
        } else {
            visitIntInsn(Opcodes.BIPUSH, 1);
            visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
        }

        visitMethodInsn(INVOKESTATIC, INSTRUMENTJ_STATIC_PROFILER_INTERFACE, METHOD_ENTER_PROBES,
                METHOD_ENTER_PROBES_DESC);
    }

    /**
     * Adds a call to
     * {@link StaticProfilerInterface#methodExitProbes(String, String, int)} <br>
     * <br>
     * {@inheritDoc}
     */
    @Override
    protected void onMethodExit(final int opcode) {
        // TODO: If we're exiting the constructor because of an exception then should that be counted differently?

        visitLdcInsn(className);
        visitLdcInsn(methodName);
        visitLdcInsn(methodDescription);

        visitLdcInsn(opcode);

        visitMethodInsn(INVOKESTATIC, INSTRUMENTJ_STATIC_PROFILER_INTERFACE, METHOD_EXIT_PROBES,
                METHOD_EXIT_PROBES_DESC);
    }

    @Override
    public String toString() {
        return super.toString() + " for " + className + "." + methodName + "(" + methodDescription + ")";
    }
}