本文可以解决如下两个问题:

1.如何处理和调试那些只发生在生产环境(或其他远程环境)而本地开发环境可能没办法重现的“问题”。

2.只有一个可以部署的war/jar包,只有class没有java源代码,而应用部署在本地/远程后,如何去调试

解决方案:部署远程调试

远程调试包括两个步骤:

  1. 启动Tomcat启用远程调试
  2. 用 IDE (这里用IntelliJ IDEA)要能够调试远程Tomcat应用

Tomcat启用远程调试

根据tomcat所运行的操作系统而有些微的不同。但是不管用哪种方法,这些配置的背后都做了同一件事:传递特定的启动参数给 JVM,让它启用远程调试(remote debugging)。

JVM 激活远程调试的启动参数有 JPDA_OPTS, CATALINA_OPTS 和 JAVA_OPTS。其中 JAVA_OPTS 是通常不建议使用的, 因为基于 JAVA_OPTS 的参数设定会暴露给所有的 JVM 应用, 而 CATALINA_OPTS 定义的设定值限制在Tomcat 内。

1 使用JPDA_OPTS

在 CATALINA_HOME/bin 目录下创建可执行脚本文件 setenv.sh ( Windows 创建 setenv.bat ),加入内容:

Linux setenv.sh

export JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=n"

Windows setenv.bat

set JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=n"

这些参数要做的事情就是启用远程调试和配置有效的选项:

  1. 指定运行的被调试应用和调试者之间的通信协议,(transport=dt_socket)
  2. 远程被调试应用开通的端口,(address=1043), 可定义其他端口,比如9999
  3. server=y 表示这个 JVM 即将被调试
  4. suspend=n 用来告知 JVM 立即执行,不要等待未来将要附着上/连上(attached)的调试者。如果设成 y, 则应用将暂停不运行,直到有调试者连接上
   suspend=y的一个比较适用的场景是,当debug一个会阻止应用成功启动的问题时, 通过suspend=y可以确保调试者连上来之后再启动应用,否则应用已经启动报错了再调试也没意义了。

当然上面的设置也可以直接放到 catalina.sh (catalina.bat )内,但是有个 setevn.* 额外的配置文件一直是最佳选择, tomcat会自动读取。

还有一种比较老的配置方法来启用远程调试:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=1043,suspend=n

-Xdebug and -Xrunjdw 与我们上面推荐的设置不同之处在于, 它是一种旧方式,适用于JVM 小于 JAVA 5.0 的版本(包括5.0), 而 agentlib:jdwp适用于 JAVA 5.0 和以后版本。

最后通过下面的命令行启动tomcat,即可完成tomcat启用远程调试啦。

$CATALINA_HOME/bin/catalina.sh jpda start

2 使用 JAVA_OPTS / CATALINA_OPTS

如果你是在 Windows 系统把 Tomcat 作为系统服务来运行的,直接打开 Apache Tomcat 的属性对话框,在Java Tab也添加启动参数:

    -agentlib:jdwp=transport=dt_socket,
address=1043,server=y,suspend=n
请确保每一条配置都是新的行,参数选项之间没有空格

但如果Tomcat没有作为 Windows 系统服务, 启用方法与前面类似,在 setenv.bat 文件中写入:

set CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=n"

如果运行在Linux上, setenv.sh 中写入:

export CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=n"

按照普通的方式启动Tomcat即可;

    ./startup.sh
或者
./catalina.sh start

3 使用JPDA启动

最后一种启用远程调试的方式是用 JPDA 切换, 用如下的启动命令将使用默认值自动启用远程调试,

catalina jpda start

该命令默认使用的设置是

-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n

如果你想要修改默认设置中的选项怎么办?可以通过修改 Tomcat 需要的这些环境变量来实现:

    //JPDA_TRANSPORT: 指定 jpda 传输协议
//JPDA_ADDRESS: 指定远程调试端口
//JPDA_SUSPEND: 指定 jvm 启动暂缓 export JDPA_ADDRESS=”8080“

然后再运行 catalina jpda start , 那么远程调试的端口将变成8080

配置Intellj Idea

确定远程 Tomcat 启动的应用已经开启了远程调试, 下一件事情就是配置Intellij Idea了。这里仍然有两种方式:Remote Tomcat 或者 Remote。

1 使用 Remote Tomcat 配置

首先保证 IDEA 里面已经打开了需要远程调试的工程源码,

然后点击 Run ➝ Edit Configurations ➝ + 按钮 ➝ Tomcat Server ➝ Remote

输入必要的远程 IP 地址和端口(Tomcat http端口);

然后转到 Startup / Connnection Tab 页,选择 ”Debug", 输入远程调试端口。

保存后,开始 debug 启动远程调试,如果运行成功会显示如下的界面,然后在源码加断点开始调试。

2 使用 Remote 配置(推荐)

第一个方法有个缺陷,你打开的工程源码必须是编译通过的工程,否则会启动会报错;

第二种方法可以在你的工程目录,不是一个完整的可以部署的工程,甚至是一个解压缩的 war/ jar 的情况下都可以调试。

同上步骤,只是选择“Remote",然后输入Name, 修改Host, Port 即可, 保存后开始Debug。

二。如果只有一个可部署的war包,没有源码,在远程已经部署完毕。这时我想调试那个远程应用,怎么做呢?

解压缩war包到一个文件夹,然后用Intellij Idea打开这个文件夹,编译的Class都在 WEB-INF/classes 目录下

找到要debug的那个class, 通过Idea反编译出来的类代码,拷贝到一个新的文件Name.java

虽然可以看到各种的编译错误,但是完全不影响你启动,代码中加断点和调试。

远程JVM调试怎么工作的

一切源于被称作 Agents 的东西。

运行着各种编译过的 .class 文件的JVM, 有一种特性,可以允许外部的库(Java或C++写的libraries)在运行时注入到 JVM 中。这些外部的库就称作 Agents, 他们有能力修改运行中 .class 文件的内容。

这些 Agents 拥有的这些 JVM 的功能权限, 是在 JVM 内运行的 Java Code 所无法获取的, 他们能用来比如修改运行中的源码, 性能分析等。 像 JRebel 工具就是用了这些功能达到的效果。

传递一个 Agent Lib 给 JVM, 通过添加 agentlib:libname[=options] 格式的启动参数即可办到。像上面的远程调试我们用的就是 ""-agentlib:jdwp=... ""来引入 jdwp 这个 Agent 的。

jdwp 是一个 JVM 特定的 JDWP(Java Debug Wire Protocol) 可选实现,用来定义调试者与运行JVM之间的通讯,它的是通过 JVM 本地库的 jdwp.so 或者 jdwp.dll 支持实现的。

简单来说, jdwp agent 会建立运行应用的 JVM 和调试者(本地或者远程)之间的桥梁。既然他是一个Agent Library, 它就有能力拦截运行的代码。

在 JVM 架构里, debugging 功能在 JVM 本身的内部是找不到的,它是一种抽象到外部工具的方式(也称作调试者 debugger)。这些调试工具或者运行在 JVM 的本地 或者在远程。这是一种解耦,模块化的架构。

最新文章

  1. CYQ.Data V5 MDataTable 专属篇介绍
  2. Microsoft Visual Studio正忙解决办法
  3. ArrayList源码分析
  4. 时间与NSString转换
  5. VNC与Windows之间的复制粘贴
  6. ASP.NET中Server对象的几个方法
  7. 【模拟】Codeforces 691C Exponential notation
  8. 微信支付(APP)
  9. BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法
  10. 提交变更(git commit)
  11. docker删除镜像文件时,出现image is referenced in multiple repositories如何解决
  12. spring中的springSecurity安全框架的环境搭建
  13. win10常见问题处理办法
  14. Entity Framework Code First - Change Tracking
  15. u3d 加载PNG做 UI图片
  16. 《算法C语言实现》————快速-查找算法(quick-find algorithm)
  17. 在浏览器输入url后并回车发生了哪些过程
  18. jenkins持续集成python cases
  19. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)
  20. 小技巧处理div内容溢出

热门文章

  1. MongoDB查询或修改内嵌文档
  2. SpringBoot博客开发之异常处理
  3. BUUCTF-[CISCN2019 华东北赛区]Web2
  4. client-go实战之二:RESTClient
  5. RabbitMQ-如何保证消息在99.99%的情况下不丢失
  6. Spring AOP 事务配置(实现转账事务)
  7. FastJson之autotype bypass
  8. undefined和null
  9. html 表单input disabled属性提交后台无法获得数据
  10. 队列,一种"公平"的数据结构