de.zib.sfs.instrument.ShutdownAdapter.java Source code

Java tutorial

Introduction

Here is the source code for de.zib.sfs.instrument.ShutdownAdapter.java

Source

/*
 * Copyright (c) 2017 by Robert Schmidtke,
 *               Zuse Institute Berlin
 *
 * Licensed under the BSD License, see LICENSE file for details.
 *
 */
package de.zib.sfs.instrument;

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

import de.zib.sfs.instrument.statistics.LiveOperationStatisticsAggregator;

public class ShutdownAdapter extends ClassVisitor {

    public ShutdownAdapter(ClassVisitor cv) {
        super(Opcodes.ASM5, cv);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        MethodVisitor mv;
        if (isHaltOrShutdownMethod(access, name, desc, signature, exceptions)) {
            // because who needs shutdown hooks anyway
            mv = new HaltAndShutdownMethodAdapter(this.api,
                    this.cv.visitMethod(access, name, desc, signature, exceptions), access, name, desc);
        } else {
            mv = this.cv.visitMethod(access, name, desc, signature, exceptions);
        }
        return mv;
    }

    private static class HaltAndShutdownMethodAdapter extends AdviceAdapter {

        protected HaltAndShutdownMethodAdapter(int api, MethodVisitor mv, int access, String name, String desc) {
            super(api, mv, access, name, desc);
        }

        @Override
        protected void onMethodEnter() {
            String liveOperationStatisticsAggregatorInternalName = Type
                    .getInternalName(LiveOperationStatisticsAggregator.class);
            this.mv.visitFieldInsn(Opcodes.GETSTATIC, liveOperationStatisticsAggregatorInternalName, "instance",
                    Type.getDescriptor(LiveOperationStatisticsAggregator.class));
            this.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, liveOperationStatisticsAggregatorInternalName,
                    "shutdown", Type.getMethodDescriptor(Type.VOID_TYPE), false);
        }

    }

    // Helper methods

    private static boolean isHaltOrShutdownMethod(int access, String name, String desc, String signature,
            String[] exceptions) {
        // shutdown() is called by JNI during regular termination of the JVM,
        // halt(exitCode) is called when the user terminates the JVM via
        // System.exit(errorCode); or Runtime.halt(exitCode);
        return access == Opcodes.ACC_STATIC
                && (("halt".equals(name) && Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE).equals(desc))
                        || ("shutdown".equals(name) && Type.getMethodDescriptor(Type.VOID_TYPE).equals(desc)))
                && null == signature && (exceptions == null || exceptions.length == 0);
    }

}