繁体   English   中英

使用Instrumentation API时,JVM会因EXCEPTION_ACCESS_VIOLATION而崩溃

[英]JVM crashes with EXCEPTION_ACCESS_VIOLATION when using Instrumentation API

我正在尝试通过Instrumentation API使用ClassFileTransformer 但是,我的JVM在我的premain方法完成之前崩溃了。

我正在使用javassist来操纵已加载类的字节码。

我的ClassFileTransformer看起来像这样:

import java.io.File;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.Modifier;

public class JSGMain implements ClassFileTransformer {
    public static void premain(String agentArguments, Instrumentation instrumentation) {
        System.out.println("premain");
        instrumentation.addTransformer(new JSGMain());
        System.out.println("end premain");
    }

    public byte[] transform(
            ClassLoader loader, String className,
            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) throws IllegalClassFormatException 
    {
        System.out.println("class="+className);
        if (className == null) {
            return classfileBuffer;
        }
        className = className.replace('/', '.');
        // Check if class should be excluded / included
        if (isExcluded(className) || !isIncluded(className)) {
            return classfileBuffer;
        }
        // If the class object is loaded but an exception is thrown we must detach it in the finally block
        CtClass classObj = null;
        // If we do not make any modifications we return the original byte code
        byte[] result = classfileBuffer;

        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass exceptionClass = pool.get("java.lang.Exception");
            // Load class file
            classObj = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
            // Dont manipulate interfaces
            if (!classObj.isInterface()) {
                // Manipulate class methods
                CtBehavior[] methods = classObj.getDeclaredBehaviors();
                for (int i = 0; i < methods.length; i++) {
                    // Dont manipulate abstract or native methods
                    if (canTransformMethod(methods[i])) {
                        System.out.println("method="+methods[i].getName());
                        addMethodCallback(className, methods[i], exceptionClass);
                    }
                }
                // If class was modified we return the new byte code
                result = classObj.toBytecode();
            }
        } catch (Exception e) {
            System.err.println("className="+className);
            e.printStackTrace();
        } finally {
            // We might not have modified the class at all
            if (classObj != null) {
                System.out.println("beforeDetach="+classObj.getName());
                classObj.detach();
                System.out.println("afterDetach="+classObj.getName());
            }
        }
        // Return either original byte code or modified byte code
        return result;
    }

    private boolean canTransformMethod(CtBehavior method) {
        return !isAbstract(method) && !isNative(method);
    }

    private boolean isAbstract(CtBehavior method) {
        return (method.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
    }

    private boolean isNative(CtBehavior method) {
        return (method.getModifiers() & Modifier.NATIVE) == Modifier.NATIVE;
    }

    private boolean isStatic(CtBehavior method) {
        return (method.getModifiers() & Modifier.STATIC) == Modifier.STATIC;
    }

    private void addMethodCallback(String className, CtBehavior method, CtClass exceptionClass) throws Exception {
        String methodName = method.getName();
        String beforeCallback;
        String afterCallback;
        if (method.getMethodInfo().isConstructor()) {
            beforeCallback = getClass().getName()+".beforeConstructor(\""+className+"\");";
            afterCallback = getClass().getName()+".afterConstructor(this);";
        } else if (isStatic(method)) {
            beforeCallback = getClass().getName()+".beforeStaticMethod(\""+className+"\", \""+methodName+"\");";
            afterCallback = getClass().getName()+".afterStaticMethod(\""+className+"\", \""+methodName+"\");";
        } else {
            beforeCallback = getClass().getName()+".beforeMethod(this, \""+methodName+"\");";
            afterCallback = getClass().getName()+".afterMethod(this, \""+methodName+"\");";
        }
        method.insertBefore(beforeCallback);
        method.insertAfter(afterCallback);

        String catchCallback = "{"+getClass().getName()+".exception(e); throw e;}";
        method.addCatch(catchCallback, exceptionClass, "e");
    }
}

它适用于大多数程序,但是当我尝试在AWT / Swing application程序上使用此类加载器时, JVM崩溃并显示以下日志:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000005e592f19, pid=2456, tid=5044
#
# JRE version: Java(TM) SE Runtime Environment (8.0_05-b13) (build 1.8.0_05-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.5-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# V  [jvm.dll+0x132f19]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

(日志对于我来说太长了,无法发布)在日志中,这一行引起了我的注意:

Event: 3.592 Executing VM operation: ParallelGCFailedAllocation

这可能是导致我出错的原因,但是我不知道如何解释它或如何解决它。

这是我启动程序的方式:

java -Xbootclasspath/p:JSG.jar -javaagent:JSG.jar -jar App.jar

感谢您的时间和帮助。

我发现了问题所在:内存不足。

premain方法确实结束了,但是在打印文本之前,JVM已经崩溃了。

事实证明,AWT和Swing调用了方法的重载,我正在对被调用的任何方法进行一些操作,而这些操作对于系统来说实在太多了。 我为什么不知道为什么它没有因为OutOfMemoryException而失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM