远程调试二三事(一)JNI的异常

533 阅读3分钟

一、起因

在测试环境中,某一个业务每次执行都会失败,但是在开发环境不会,并且不会有任何异常报出。JDK版本一致,打包可以正常运行,这时候我通过远程调试找到了这个程序中的问题。

部署环境

  • 华为云
  • window server 2016
  • springboot
  • jdk8

二、远程调试

由于该错误只发生在部署环境,所以需要连接云服务器远程调试。查了一下资料,IDEA是支持远程DEBUG模式的(默认端口是5005),所以需要先配置端口。

1. 开发端口

在安全组开放端口5005,这个端口用于socket获取堆栈信息。不同云平台的设置可能不太一样,请自行查询。

image.png

2. 命令行启动

通过以下命令启动DEBUG模式

start /b java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 XX.jar -Dfile.encoding=utf-8

参数含义如下:

  • -Xdebug 表示启动debug模式
  • -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
    • -Xrunjdwp 用于通知JVM使用(java debug wire protocol)来运行调试环境
    • transport指定了调试数据的传送方式
      • transport=dt_socket 表示监听socket;还有dt_shmem(共享内存方式)类型,但只适用于Windows平台
      • server=y 启用server模式
      • address=5005 表示通过5005监听socket连接

JVM参数中有 -X 以及-XX,其中 以 -X 开头的是非标准选项(大版本区别);-XX 的选项是不稳定、不建议随便使用

3. 通过IDEA监听

选择 Remote JVM Debug 类型的执行配置

image.png

填写对应的IP

image.png

启动提示

image.png

java.lang.UnsatisfiedLinkError是一个跟JNI相关的异常,在Native.Open()方法中触发了,这个异常在部署环境的机子中存在,但没有报错,但在开发环境中却没有任何异常。以前没有遇到这个bug,记录一下仅供参考。

4. 补全缺失的DLL

由于相关代码涉及到JNI,所以应该是和DLL有关,本人的机子是WIN10且安装过多个更新,无法确定缺失的DLL。这时候就可以用神器dependency walker了。

Dependency Walker 是一款免费实用程序,可扫描任何 32 位或 64 位 Windows 模块(exe、dll、ocx、sys 等)并构建所有依赖模块的层次树图。对于找到的每个模块,它会列出该模块导出的所有函数,以及其他模块实际调用了哪些函数。另一个视图显示所需文件的最少集合,以及每个文件的详细信息,包括文件的完整路径、基址、版本号、机器类型、调试信息等。Dependency Walker 对于解决与加载和执行模块相关的系统错误也非常有用。Dependency Walker 可以检测许多常见的应用程序问题,例如缺少模块、无效模块、导入/导出不匹配、循环依赖错误、模块机器类型不匹配以及模块初始化失败。

下载地址如下: 官网

用它加载对应的DLL,缺失的DLL会标红,如下所示:

image.png

下载缺失的DLL后,放到代码可扫描到的路径即可。我是将缺失的DLL放置到C:\Windows\System32路径后相关功能可以执行,问题解决!!

三、参考

Java远程调试 java -Xdebug各参数说明