使用byte buddy的Advice时,抛出Exception of java.lang.NoClassDefFoundError

When using Advice of byte buddy, Exception of java.lang.NoClassDefFoundError is throwed

出于某种原因,我一直在分析我自己的旧 jar 文件(不幸的是源代码丢失了)。 我知道我要找到哪个部分,但不记得它在哪里。 所以决定使用byte buddy来获取jar文件的所有运行流。记录所有 classes 中所有方法的参数值和 return 值就足够了(库 class 除外,例如 java.lang.*)。 我尝试了稍作修改的示例代码,但只出现了一个例外:

 public static void premain(final String agentArgs,
                           final Instrumentation inst) {
    System.out.println(
            "+++Hey, look: I'm instrumenting a freshly started JVM!");
    new AgentBuilder.Default()
            .type(ElementMatchers.any())
            .transform(new MetricsTransformer())
            .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
            .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
            .installOn(inst);
}

private static class MetricsTransformer implements AgentBuilder.Transformer {
    @Override
    public DynamicType.Builder<?> transform(
            final DynamicType.Builder<?> builder,
            final TypeDescription typeDescription,
            final ClassLoader classLoader,
            final JavaModule module) {

        final AsmVisitorWrapper methodsVisitor =
                Advice.to(EnterAdvice.class, ExitAdviceMethods.class)
                        .on(ElementMatchers.isAnnotatedWith(CollectMetrics.class)
                                .and(ElementMatchers.isMethod()));

        final AsmVisitorWrapper constructorsVisitor =
                Advice.to(EnterAdvice.class, ExitAdviceConstructors.class)
                        .on(ElementMatchers.isAnnotatedWith(CollectMetrics.class)
                                .and(ElementMatchers.isConstructor()));

        return builder.visit(methodsVisitor).visit(constructorsVisitor);
    }

    private static class EnterAdvice {
        @Advice.OnMethodEnter
        static long enter() {
            return System.nanoTime();
        }
    }

    private static class ExitAdviceMethods {
        @Advice.OnMethodExit(onThrowable = Throwable.class)
        static void exit(@Advice.Origin final Executable executable,
                         @Advice.Enter final long startTime,
                         @Advice.Thrown final Throwable throwable) {
            final long duration = System.nanoTime() - startTime;
            System.out.println(duration);;
        }
    }

}

字节哥的版本是1.9.5,1.7.11 jdk版本:1.8.0.191

和 cmd 中的异常:

    E:\>cd E:\workshop\_android_studio\BounAgent\out\artifacts\BounAgent_jar

E:\BounAgent_jar>java -javaagent:BounAgent.jar -jar untitled.jar
Exception in thread "main" java.lang.NoClassDefFoundError: net/bytebuddy/matcher
/ElementMatcher
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.getDeclaredMethod(Unknown Source)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(Unknown Sou
rce)
        at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(Unknown So
urce)
Caused by: java.lang.ClassNotFoundException: net.bytebuddy.matcher.ElementMatche
r
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 5 more

本机方法中的致命错误:-javaagent 处理失败

提前致谢。

根据an article我发现:

To launch your agent you must bundle the agent classes and resources in a jar, and in the jar manifest set the Agent-Class property to the name of your agent class containing the premain method. (An agent must always be bundled as a jar file, it cannot be specified in an exploded format.)

您的代理 JAR 文件 ("BounAgent.jar") 似乎未包含正确形式的所有依赖项。具体来说,bytebuddy 类 不在 JAR 文件中。这导致代理 类 无法加载。