SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析

一. netty客户端通过ssl方式连接服务端失败

  • 最近在重构项目代码,在测试时在本地通过ssl的方式连接服务端,服务端通过SniHandler处理ssl连接时,报一下异常:

    2019-05-27 17:32:26,104 110948 [nioEventLoopGroup-3-2] ERROR c.t.p.b.m.h.ChannelDisconnectedHandler(128) -  Could not initialize class io.netty.handler.ssl.OpenSslEngine
    

二. debug代码分析问题

  1. netty处理ssl解析的ChannelHandler是SniHandler,故debug代码分析问题,在SniHandler的decode解码方法设置断点:
    SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第1张图片
  2. 然后运行服务端,并通过netty客户端连接服务端:
    • 在debug过程中,首先调用到了抛出了java.lang.NoSuchMethodError的异常,表示没有io.netty.util.internal.PlatformDependent.newAtomicIntegerFieldUpdater方法的异常,由于catch掉了,故代码可以继续运行。
    • 然后出现java.lang.NoClassDefFoundError: Could not initialize class io.netty.handler.ssl.OpenSslEngine,如下图所示。异常NoClassDefFoundError为运行时加载不到类,说明在运行时,在项目中加载不到io.netty.handler.ssl.OpenSslEngine这个类,所以需要定位这个io.netty.handler.ssl.OpenSslEngine所在的包。关于这个异常的知识可以参考我的另外一篇文章:
      Java类加载失败异常:NoClassDefFoundError与ClassNotFoundException

      SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第2张图片堆栈情况:

三、包分析与定位问题

  1. 查找io.netty.handler.ssl.OpenSslEngine所在的包,如下在idea的External Libraries视图可以发现,io.netty.handler.ssl.OpenSslEngine这个类位于netty-all.jar包中:

  2. 在项目目录下,通过mvn dependency:tree命令分析当前项目依赖的包关系:netty相关的包依赖如下,并没有netty-all.jar的依赖,所以可以定位出是由于不存在这个包导致的。如下对netty-common.jar包加红,后面会继续分析这个包。
    SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第3张图片

  3. 所以在项目的pom.xml文件中添加这个包的依赖,如下:在netty-codec-mqtt后面添加netty-all的包。
    SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第4张图片

  4. 重新启动项目,发现还是报同样的错误,如下:

    2019-05-27 20:32:29,104 110948 [nioEventLoopGroup-3-2] ERROR c.t.p.b.m.h.ChannelDisconnectedHandler(128) -  Could not initialize class io.netty.handler.ssl.OpenSslEngine
    
    • 但是通过mvn dependency:tree命令分析项目确实是已经有了netty-all.jar这个包,如下:netty-common.jar此时在netty-all.jar前面。
      SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第5张图片
    • 所以此时可能的情况就是项目在运行的时候并没有使用到netty-all.jar里面的类,而是使用了其他netty相关包,其实此时使用的就是netty-codec-mqtt.jar包引入的netty-common.jar包里面的类。结合之前的方法io.netty.util.internal.PlatformDependent.newAtomicIntegerFieldUpdater找不到的异常:去netty-common.jar包发现里面也存在这个子包,如下:在idea查找newAtomicIntegerFieldUpdater这个方法,显示查找不到。故项目在运行的时候,定位到的是netty-common.jar包内部的io.netty子包,在这个子包里面查找:io.netty.util.internal.PlatformDependent.newAtomicIntegerFieldUpdater和io.netty.handler.ssl.OpenSslEngine都查找不到

四、解决方法

  • 通过在maven的pom.xml文件配置项目的包依赖关系有个规则:优先使用在pom.xml文件中,配置在前面的依赖包。刚刚没有使用netty-all.jar是因为netty-all.jar配置在了netty-codec-mqtt.jar的后面,故使用了netty-codec.mqtt.jar所引入的netty-common.jar包。
    解决方法如下:将netty-all.jar和netty-codec-mqtt.jar的位置调换一下,netty-all.jar配置在前面。
    SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第6张图片

  • 如下:netty-all.jar在netty-common.jar前面了。
    SSL方式连接Netty服务端失败:OpenSslEngine类无法加载NoSuchMethodError异常排查分析_第7张图片

  • 重启项目,通过netty客户端重新连接服务端,此时可以正常连接到了,到了项目自身的身份认证部分了,如下:

    2019-05-27 21:07:25,249 52602 [nioEventLoopGroup-3-1] ERROR c.t.p.b.m.s.HttpsCredentialRealm(210) - user info:{"data":{"error_message":"access_token 错误","error_description":"很抱歉,身份验证失效,请重新登录","error_code":10501,"error":"invalid_token"},"is_succ":false}
    

你可能感兴趣的:(工作笔记)