zoukankan      html  css  js  c++  java
  • dubbo服务provider方打印警告日志,getDeserializer

    2018-09-12 16:16:44 WARN [New I/O worker #1] SerializerFactory.java:652 getDeserializer - Hessian/Burlap: 'com.xxx.xxxBolt$1' is an unknown class in sun.misc.Launcher$AppClassLoader@a2c6f70

    今天下午4点过商品组同事反馈,线上他们那边有个dubbo服务A(provider)打印了很多WARN日志让看看。

    这个日志是在dubbo的hessian-lite模块下SerializerFactory类,Deserializer getDeserializer(String type)方法中打印的:

    看名称大概是获取反序列化类。在服务A中接口方法是能正常调用的,不影响业务。但是该方法调用很频繁,大量这样的WARN日志显然不好。

    其实这个问题之前遇到过,当时是dubbo的provider方接口有升级,方法入参vo有变动,consumer端依赖了provider放的api interface包,没有及时重新构建发布。

    不过看这次日志打印很奇怪,'com.xxx.XxxBolt$1' is an unknown class,XxxBolt是我们这边一个storm拓扑(比如拓扑T)中的一个bolt名称,在该bolt中调用了服务A的一个接口;

    服务A依赖了包B,B下面有个枚举类C;

    该接口方法签名为 Map<枚举类C, Object> 方法名(Long xxId, Set<枚举类C> xxSet);

    检查XxxBolt中调接口的代码,

    调用如下:

    Long xxId = ...;
    
    Set<类B, Object> xxSet = new HashSet{{
    
          add(枚举C.枚举1,xxx);
    
          add(枚举C.枚举2,xxx);
    
          ...
    
    }}
    
    Map<枚举类C, Object> result = 方法名(Long xxId, Set<枚举类C> xxSet);

    看代码中并没有把XxxBolt作为参数传递,而且服务A没有依赖storm拓扑的项目,怎么日志里会打印出XxxBolt的类名呢?

    这个问题先放着,我们先回想了一下:服务A上周有过改动构建发布,storm的拓扑T的XxxBolt也有改动并发布,不过可以确定的是这段调用代码,包括请求参数,是没有改动的;

    刚才提到,服务A依赖了包B,包B也有改动;那么拓扑T是否是在服务A、包C构建之后构建发布的呢?(虽然记忆中是按的这个顺序)

    在jenkins上查看构建记录,包B是9月5号上午11点构建的,服务A是下午4点构建发布的,我们这边的拓扑T是下午5点以后构建发布的;

    在storm UI上去看拓扑的Uptime,已启动了5天多10多个小时,推算下时间,也证明拓扑T是构建后重启的;

    综上2点,说明拓扑T的依赖(A和B)都是最新的,应该不存在provider和consumer枚举C类不一致的问题。

    跟同事沟通确定这点后都有些疑惑。尝试把拓扑T构建打包后的jar下到本地,解压出来看class文件,发下XxxBolt类所在包下,不仅有XxxBolt.class,还多了一个XxxBolt$1.class;

    再回头看日志'com.xxx.XxxBolt$1' is an unknown class,这时才注意到日志里说找不到类的名称,XxxBolt后面多了$1,之前看漏了- -!

    想起java编译生成class文件,如果定义了内部类会产生xxx$xxx的class文件;

    可记得XxxBolt类里面并没有定义内部类啊,翻看一遍代码确实没有。

    用反编译工具打开XxxBolt$1.class:

    import com.xxx.枚举B;
    import java.util.HashSet;
    
    class 1 extends HashSet<枚举B>
    {
    }
    

    类名是1,这样XxxBolt$1名称解释得通,但它是哪里产生的呢? 

    刚才枚举B已确定是最新的,于是我们把目光锁定在了这个HashSet的构造上

    Set<类B, Object> xxSet = new HashSet{{
    
          add(枚举C.枚举1,xxx);
    
          add(枚举C.枚举2,xxx);
    
          ...
    
    }}

    这里使用了快捷的初始化数据语法,即在{{}}里用add的方式;
    尝试把XxxBolt代码里的某个Map xxx = new HashMap也用这种写法,重新编译发现生成了XxxBolt$2.class,反编译打开是class 2 extends HashMap<>...

    那么问题找到了,拉分支把这段代码修改下:

    Set<类B, Object> xxSet = new HashSet<类B, Object>();
    xxSet.add(枚举C.枚举1, xxx);
    xxSet.add(枚举C.枚举2, xxx);
    ...

    用普通的初始化方式,先new好,在用对象调add方法。

    重新编译就只有XxxBolt.class了。

    依次合并代码至主干后,重新构建发布并重启拓扑T,再观察服务A中已没有这个警告日志了。

    问题解决:)

    -------------------------------------------------------------------------------------------------------------------------------------------------

    总结:

    dubbo服务provider和consumer中入参要保持一致,入参vo有类型或结构变动,consumer端需要跟着provider构建,依赖最新的包;

    HashSet、HashMap用快捷初始化语法时,编译会产生内部类,以Xxx$1这种命名方式,在dubbo接口方法参数中如果用Set、Map类型,则需要注意用普通的方式初始化;

    -------------------------------------------------------------------------------------------------------------------------------------------------

    参考:

    【解决】hessian 客户端报警告:Hessian/Burlap: xxx is an unknown class in sun.misc.Launcher…… https://blog.csdn.net/fangzhangsc2006/article/details/7975978

    警告: Hessian/Burlap: 'com.github.pagehelper.Page' is an unknown class in WebappClassLoader https://blog.csdn.net/qq_38765404/article/details/78108780

  • 相关阅读:
    oracle10g安装问题
    oracle10g卸载问题
    c编译过程
    根文件系统制作
    Handler消息传递机制
    Glide图片加载库的使用
    关于FragmentPageAdapter
    Android中set标签的使用
    overridependingtransition方法
    关于View
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/9638327.html
Copyright © 2011-2022 走看看