今天在调试时又遇到行号无法对齐的问题,因为之前开发 Java Agent 时遇到过,常见于源码 jar 与运行时 jar 不一致导致,本文简要记录。
调试的类为 javax.servlet.annotation.MultipartConfig
,即最常见的 Servlet API 中的类,比如对以下四个字段打上了断点:
你会发现断点停在了类上的注释处,查询应用中对 Servlet API 的依赖为:
1 | <dependency> |
说明 IDE 是使用的 javax.servlet-api
对应的 jar 包内容进行显示,而我们知道运行时是使用的 Tomcat lib 目录中的 servlet-api.jar,于是我将该 jar 解压,并执行命令 javap -v MultipartConfigElement.class
,输出如下:
1 | Classfile /private/tmp/javax/servlet/MultipartConfigElement.class |
从以上的字节码信息中可以看出 line 48 正在执行 public javax.servlet.MultipartConfigElement(java.lang.String, long, long, int)
方法中对 location
字段的相关操作,很明显,与 javax.servlet-api
源码不匹配。查询 Tomcat 对应版本的源码,很容易发现 lib 目录中的 servlet-api.jar 由 Tomcat 中的源码构建而来,源码位于 MultipartConfigElement.java at 8.5.56:
1 | /* |
其中 48 行与我们反编译的字节码文件匹配。明确原因后,我将工程里的依赖调整为:
1 | <dependency> |
调整后断点暂停的位置正常。我比较了 JavaEE 与 Tomcat 中关于 servlet-api 的类,发现其主要的不同在于注释部分,导致行号无法对上,JavaEE 中 MultipartConfigElement.java
的源码可以参考:servlet-spec/MultipartConfigElement.java at 3.1.0。
Reference
Chapter 4. The class File Format - 4.7.12. The LineNumberTable Attribute
Java LineNumberTable: Entry explanation - Stack Overflow