首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用NoClassDefFoundError实现OpenTracing时如何避免OpenTracing

在使用NoClassDefFoundError实现OpenTracing时如何避免OpenTracing
EN

Stack Overflow用户
提问于 2019-07-08 12:42:57
回答 1查看 642关注 0票数 3

我正在尝试实现一个Java,该代理可以轻松地添加到我们的一些遗留服务的命令行中,以便使用OpenTracing API支持分布式跟踪。到目前为止,我使用的是ByteBuddy (1.9.12)并在工具化代码运行到以下场景时命中NoClassDefFoundErrors

  1. java.util.concurrent包中检测一个类:找不到GlobalTracer,因为Java只在应用类路径中。通过将包含跟踪API的Java代理添加到命令行上的引导类路径(仅限于Java 8),我暂时解决了这一问题,但我希望能够以编程的方式做到这一点。寻找正确的方法来做到这一点。(编辑:这是通过在Java的清单文件中使用Boot-Class-Path选项来解决的--只需将Java本身的文件名--没有路径--放在其中。)
  2. 检测自定义网络客户端类:无法从我的Intercept类(字节码注入期间)在自定义网络包中找到类,因为网络客户端包不在Java Agent JAR中。我正在寻找一种“正确的方式”来构造一个高层次的东西,以避免这种情况。

方案2的代码:

代码语言:javascript
复制
public class NettyAgentRule implements AgentRule {

    public Iterable<? extends AgentBuilder> buildAgent(AgentBuilder agentBuilder) {
        return Arrays.asList(agentBuilder
                .type(hasSuperType(named("org.jboss.netty.bootstrap.Bootstrap")))
                .transform((builder, typeDescription, classLoader, module) -> {
                    return builder.visit(Advice.to(NettyAgentRule.class).on(named("setPipelineFactory")));
                }));
    }

    @Advice.OnMethodEnter
    public static void enter(final @Advice.Origin String origin,
                            final @Advice.This Object thiz,
                            @Advice.Argument(value = 0, readOnly = false, typing = Assigner.Typing.DYNAMIC) Object parameter) {
        parameter = NettyAgentIntercept.enter(thiz, parameter);
    }
}

其中错误发生在引用Netty类的NettyAgentIntercept类中。

我已经研究了OpenTracing‘cont肋骨’SpecialAgent是如何处理这些场景的,它有相当多的自定义类加载,这些类加载与它们的构建结构紧密耦合( JAR中的JAR遵循命名约定)。如果可能的话,最好避免这样做。

场景2中的异常堆栈示例:

代码语言:javascript
复制
java.lang.NoClassDefFoundError: org/jboss/netty/channel/ChannelPipelineFactory
2019-07-05 18:52:21,10613       at com.example.tracing.netty.NettyAgentIntercept.enter(NettyAgentIntercept.java:9)
2019-07-05 18:52:21,10613       at org.jboss.netty.bootstrap.Bootstrap.setPipelineFactory(Bootstrap.java:251)
2019-07-05 18:52:21,10616       at com.example.lib.util.net.NettyCore.<init>(NettyCore.java:176)
2019-07-05 18:52:21,10616       at com.example.lib.util.net.NetClient.getInstance(NetClient.java:125)
2019-07-05 18:52:21,10617       at com.example.lib.util.net.NetClient.getInstance(NetClient.java:147)
2019-07-05 18:52:21,10617       at com.example.lib.util.net.NetClient.getInstance(NetClient.java:55)
2019-07-05 18:52:21,10617       at com.example.component.Component.main(Component.java:155)
2019-07-05 18:52:21,10618       at com.example.lib.util.invoke.ComponentThread.run(ComponentThread.java:21)

我还尝试了以下代码,建议在

byte-buddy throws java.lang.ClassNotFoundException: javax.servlet.http.HttpServlet

但这也导致了同样的例外:

代码语言:javascript
复制
public Iterable<? extends AgentBuilder> buildAgent(AgentBuilder agentBuilder) {
        return Arrays.asList(agentBuilder
                .type(hasSuperType(named("org.jboss.netty.bootstrap.Bootstrap")))
                .transform(new AgentBuilder.Transformer.ForAdvice()
                        .include(getClass().getClassLoader())
                        .advice(named("setPipelineFactory"),"com.example.tracing.netty.NettyAgentAdvice")
                ));

    }

通知类在哪里

代码语言:javascript
复制
package com.example.tracing.netty;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;

import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner;

public class NettyAgentAdvice {

    @Advice.OnMethodEnter
    public static void enter(final @Advice.Origin String origin,
                            final @Advice.This Object thiz,
                            @Advice.Argument(value = 0, readOnly = false, typing = Assigner.Typing.DYNAMIC) Object parameter) {
        parameter = enter(thiz, parameter);
    }

    public static ChannelPipelineFactory enter(Object thiz, Object returned) {
        ChannelPipelineFactory pipelineFactory = (ChannelPipelineFactory) returned;
        if (thiz instanceof ClientBootstrap) {
            return () -> {
                ChannelPipeline pipeline = pipelineFactory.getPipeline();
                if (pipeline.get(TracingHandler.class) == null) {
                    pipeline.addLast("tracing", new TracingHandler());
                }
                return pipeline;
            };
        }
        return pipelineFactory;
    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-07-08 21:29:40

字节Buddy为代理构建器提供了一个通知适配器,该适配器可以避免类加载和反射,以避免所看到的错误: AgentBuilder.Transformer.ForAdvice。

此转换器将使用TypePool解析来自目标类加载器的通知类,以及添加来表示类的任何类加载器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56935234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档