qunarcorp / bistoury

Bistoury是去哪儿网的java应用生产问题诊断工具,提供了一站式的问题诊断方案
GNU General Public License v3.0
4.01k stars 824 forks source link

在线debug断点添加失败register breakpoint fail, File was not found in the executable #40

Closed ioiioo closed 5 years ago

ioiioo commented 5 years ago

想在开发机上面试下在线debug功能,但添加断点时报错 register breakpoint fail, File was not found in the executable

Springboot jar工程是用jdk1.7版本启动的 bistoury 是用jdk1.8启动的.

tail -f bistoury/bistoury.log

java.lang.IllegalStateException: register breakpoint fail, File was not found in the executable
    at qunar.tc.bistoury.instrument.client.debugger.DefaultDebugger.doRegisterBreakpoint(DefaultDebugger.java:152) ~[bistoury-instrument-client-2.0.5.jar:na]
    at qunar.tc.bistoury.instrument.client.debugger.DefaultDebugger.registerBreakpoint(DefaultDebugger.java:96) ~[bistoury-instrument-client-2.0.5.jar:na]
    at qunar.tc.bistoury.attach.arthas.debug.QDebugClient.registerBreakpoint(QDebugClient.java:63) ~[bistoury-attach-arthas-2.0.5.jar:na]
    at qunar.tc.bistoury.attach.arthas.debug.QDebugAddCommand.process(QDebugAddCommand.java:74) ~[bistoury-attach-arthas-2.0.5.jar:na]
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82) [arthas-core-3.1.1.jar:3.1.1]
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18) [arthas-core-3.1.1.jar:3.1.1]
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111) [arthas-core-3.1.1.jar:3.1.1]
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108) [arthas-core-3.1.1.jar:3.1.1]
    at com.taobao.arthas.core.shell.system.impl.QProcessImpl$CommandProcessTask.run(QProcessImpl.java:370) [bistoury-attach-arthas-2.0.5.jar:3.1.1]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_67]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_67]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_67]

请帮下是什么原因导致失败.

ioiioo commented 5 years ago

通过cat bistoury.log | grep "Initializing ClassPathLookup, default classpath" -A 100

发现我springboot jar包里面的类不在 bistoury 扫描的目录范围内 扫描的目录为:

xxxx/xxx/springboot-tomcat-tmp/cache/tomcat_webapp/BOOT-INF/classes

而我的springboot应用真实在tomcat目录为:

xxxx/xxx/springboot-tomcat-tmp/cache/tomcat_webapp/

这两个目录并不一样

xleiy commented 5 years ago

我们现在是按照默认的springboot解压后的目录结构处理的,xxxx/xxx/springboot-tomcat-tmp/cache/tomcat_webapp/META-INF/MANIFEST.MF这个文件你那里有吗,有的话可以把内容贴一下

ioiioo commented 5 years ago

我测试机器上面的信息:

[root@444dc29b-2685-43ef-8e26-719f25e83f89 META-INF]# pwd
xxxxx/xxxx/springboot-tomcat-tmp/cache/tomcat_webapp/META-INF

MANIFEST.MF 里面的内容:

[root@444dc29b-2685-43ef-8e26-719f25e83f89 META-INF]# cat MANIFEST.MF 
Manifest-Version: 1.0
Implementation-Vendor: Pivotal Software, Inc.
Implementation-Title: xxxx-crxxtive
Implementation-Version: 0.0.1-SNAPSHOT
Implementation-Vendor-Id: xxxx
Built-By: root
Build-Jdk: 1.7.0_45
Start-Class: cn.com.xxxx.CrxxtiveApplication
Created-By: Apache Maven 3.0.5
Spring-Boot-Version: 1.3.0.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Archiver-Version: Plexus Archiver
xleiy commented 5 years ago

我们这里需要两个目录,一个是classes目录,一个是lib目录,我们想到的一个方案就是从MANIFEST.MF中读取这两个目录,正常的打包方式MANIFEST.MF文件里面是有这两个目录的,但是像你这种打包方式我们可以知道classes目录(根目录),但是lib目录在什么地方啊

ioiioo commented 5 years ago

问题己解决;主要的问题是mvn打包插件引起的。 并不是所有版本spring-boot-maven-plugin的打包插件都会在MANIFEST.MF文件中生成以下两项信息,并且打包出来的字节码文件目录也不一定相同。:

...
Spring-Boot-Classes: BOOT-INF/classes/
...
Spring-Boot-Lib: BOOT-INF/lib/

我用于测试的项目是一个老项目引用的Springboot版本是<version>1.3.0.RELEASE</version> 而对应的打包插件配置如下:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

这样的配置会引用1.3.0版本Sprinboot父工程中申明的版本,具体信息见:

spring-boot-dependencies-1.3.0.RELEASE.pom中的版本申明如下:

<spring-boot.version>1.3.0.RELEASE</spring-boot.version>
...
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>${spring-boot.version}</version>
</plugin>

可以看到这里默认定义了spring-boot-maven-plugin是跟随Sprinboot父工程中申明的版本用的是1.3.0版本的,而这个版本打出来包MANIFEST.MF文件内容是不包含Spring-Boot-Classes,Spring-Boot-Lib这两项配置的 解决办法 显示申明我工程spring-boot-maven-plugin的版本为1.5.22.RELEASE版本。具体配置变为如下:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.5.22.RELEASE</version>
</plugin>
jackiepon31 commented 4 years ago

那有办法支持老版本的打包方式吗?我们这想大规模推广的话,肯定会遇到这种兼容性的问题,建议作为一个重要特性提供