在 IntelliJ IDEA 中远程调试 Java 程序

  • 说明
  • IntelliJ IDEA 远程调试的原理
  • 使用 IntelliJ IDEA 远程调试原始 Java 程序的步骤

说明

  • 本文的远程调试对象以运行在 Linux 上的 Java 程序为例。

IntelliJ IDEA 远程调试的原理

  远程调试指的是使用本地客户端来调试运行在远程服务器上的程序。IntelliJ IDEA 远程调试的原理是,当服务器端以调试模式运行 Java 程序时,如果客户端使用文本相同的字节码和事先约定好的端口号,就可以远程调试该 Java 程序。因此,IntelliJ IDEA 远程调试的必要条件是:

  • Java 程序必须在服务端已经启动且在调试时正在运行。IntelliJ IDEA 只有触发调试的能力,没有远程部署启动 Java 程序的能力

  • Java 程序在服务端以调试模式启动。以调试模式启动需要在运行该 Java 程序时,使用一些调试模式的 JVM 参数。

  • 客户端使用 IntelliJ IDEA 进行调试时,使用与服务端事先约定好的相同端口号,且该端口号在服务端没有被占用。

  • 客户端使用 IntelliJ IDEA 进行调试时,使用的代码在文本上与服务端一致。在文本上一致指的是,客户端使用的代码与服务端使用的代码的文字完全相同,如果不一致,使用的断点将不起作用。文本上一致不包括注释,但包括换行。文本上一致不需要是同一个代码源文件,只需要文本相同即可。


  使用 IntelliJ IDEA 进行远程调试的注意事项:

  • IntelliJ IDEA 只有触发调试的能力,没有远程部署启动 Java 程序的能力。只能自己先确保 Java 程序可以在服务端基本运行之后才能在客户端使用远程调试,无法通过 IntelliJ IDEA 来直接利用服务端的环境运行 Java 代码。

  • 在远程调试时,程序是在服务端运行的,与客户端没有任何关系,产生的数据对客户端不会有任何影响。

  • 代码在文本上与服务端一致 仅指代码相同。文本上一致不包括注释,但包括换行。文本上一致不需要是同一个代码源文件,只需要文本相同即可。也不需要约定 JAR 包名,但需要使用同一标识的应用。

  • 在 IntelliJ IDEA 的代码中打断点不需要在调试之前打断点,只需要在程序运行到此断点之前打即可。一般部署在服务端的应用都是一个无限循环的应用,同一处代码会不断地运行。因此一般可以在调试时的任何时候打断点。

  • 一旦在客户端的 IntelliJ IDEA 中触发了断点,在服务端运行的 Java 程序会立刻被暂停运行,且受客户端的 IntelliJ IDEA 所控制。


  IntelliJ IDEA 远程调试有两种模式,一种是 attach,另一种是 listenattach 指的是服务端的 Java 程序已经运行,使用 IntelliJ IDEA 立即进行调试。listen 指是服务端的 Java 程序可能还没有运行,现在正在监听在服务端的该端口,直到服务端的 Java 程序启动了再触发调试。本文使用的是 attach 模式。

使用 IntelliJ IDEA 远程调试原始 Java 程序的步骤

笔者的运行环境:

  • 客户端:
  • IntelliJ IDEA 2020.1.2 (Ultimate Edition)
  • Windows 10 教育版
  • Xshell 7.0.0014
  • Xftp 7
  • 服务器:
  • CentOS Stream 8
  • Java 11.0.12
  1. 为了方便远程输入命令、将文件加入到 Linux 操作系统中,最好还要在一台 Windows 操作系统上面使用一种终端控制软件,如 Xshell、Xftp 等。关于这方面的内容,可见笔者的另一篇如下博客。同时,该博客还给出了查看 Linux 中的 IP 的方法:

    如何在 Windows 主机上访问本地局域网中的 Linux 主机:
    https://blog.csdn.net/wangpaiblog/article/details/120052152?spm=1001.2014.3001.5502

    现在,假设读者已经会了如何将文件从 Windows 中传入 Linux 中,以及查看 Linux 中的 IP。

  2. 为了方便说明,笔者编写了一个傻瓜的 Java 程序。此 Java 程序是在本地的客户端中的 IntelliJ IDEA 中完成编写的。示例代码如下:

    以下代码的简单解释:

    • 以下为无限循环延时代码。间隔时间为 1 秒,每秒会打印循环的圈数。
    • 使用无限循环的原因是,为了确保进行远程调试时,远程程序依然处于运行的状态。
    • 无需为无限循环而担心,因为这里是阻塞型程序,在 CMD 中运行时,使用 ctrl + C 即可立刻终止该程序。
    public class Main {public static void main(String[] args) throws InterruptedException {System.out.println("--------start--------");if (args != null && args.length != 0) {for (int order = 1; order <= args.length; ++order) {System.out.println(order + ":" + args[order - 1]);}} else {System.out.println("Hello world.");}for (int order = 0; true; ++order) { // 无限循环延时代码System.out.println(order);Thread.currentThread().sleep(1000); // 休眠 1 秒}}
    }
    
  3. 在 IntelliJ IDEA 中进行远程调试的相关配置。如下图所示进行操作。

  4. 如下图所示进行操作。注意复制图中的 JVM 代码,这将在之后在服务端用于以调试模式启动本程序。

    笔者示例中约定的端口号为 5005,JVM 代码为:

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

  5. 在本地客户端制作 JAR 包。

    如果读者没使用 Maven 等构建工具,打包的方法可见笔者的另一篇博客:

    不使用 Maven 等构建工具,而使用原始方法在 IntelliJ IDEA 中制作 JAR 包:
    https://blog.csdn.net/wangpaiblog/article/details/120359856?spm=1001.2014.3001.5501

    如果读者使用了 Maven,则 Maven 下打包的方法可见笔者的另一篇博客:

    将 Maven 中的多模块项目只打成一个 JAR 包:
    https://blog.csdn.net/wangpaiblog/article/details/119628194

  6. 得到 JAR 包之后,可以使用 Xftp 将其上传到服务器端的 Linux 中。

  7. 对于很多 Linux 系统,此时还不能直接进行远程调试,因为 Linux 上有防火墙,默认会阻止所有的远程访问。对于笔者的 CentOS Stream 8 x86_64,默认的防火墙为 firewalld,而不是 iptables。(很多人会选择安装 iptables,但偷懒的笔者没有选择这样做。)

    • 一个偷懒的方法就是,永久地关闭防火墙。关闭的方法如下:

      systemctl stop firewalld
      systemctl mask firewalld
      firewall-cmd --reload

    • 另一个方法是,在防火墙中永久开放上述约定的端口号 5005。开放的方法如下:

      firewall-cmd --zone=public --add-port=5005/tcp --permanent
      firewall-cmd --reload

      单独开放完端口 5005 之后,可以输入以下命令查看是否生效:

      firewall-cmd --zone=public --query-port=5005/tcp

      [root@localhost temp]# firewall-cmd --zone=public --query-port=5005/tcp
      yes
      

      实际上,也可以输入以下命令查看所有开放的端口:

      firewall-cmd --zone=public --list-ports

      [root@localhost temp]# firewall-cmd --zone=public --list-ports
      5005/tcp
      
  8. 进入上述 JAR 包的目录。假设上面上传的 JAR 包名为 demo.jar。整合前面复制的 JVM 代码,输入以下命令来运行此 demo 程序。

    java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar demo.jar

  9. 可以看到,前面的无限循环程序开始运行了。

  10. 现在就可以在本地客户端的 IntelliJ IDEA 进行远程调试了。

  11. 如果远程调试成功。在服务器端运行的上述 Java 程序会立刻被暂停运行。而在 IntelliJ IDEA 的调试控制台 Console 中会有如下显示:

  12. 最后,记得去服务器端使用 ctrl + C 终止上述 demo 程序。

  13. 尽管很多读者认真阅读了笔者的教程,但现实中仍然可能出现很多调试失败的例子。当读者远程调试失败的时候,还请再回去看笔者本文前面写的 IntelliJ IDEA 远程调试的原理,不过这里也再提几点:

    • 如果远程服务端的 Java 程序没有启动,这是一定会调试失败的。因为如果远程服务端的 Java 程序没有启动,则远程服务端的端口号会不存在。(这与有没有在防火墙对外开放端口号权限无关。如果远程服务端的 Java 程序没有启动,就会连端口号都没有,开放端口号权限也没用。)

    • 如果想知道远程服务端的端口号有没有生成,可以在远程服务端输入以下命令:(如果运行的程序阻塞了当前的 Shell 窗口,可以在 Xshell 中另开一个 Shell 窗口。)

      netstat -na | grep 5005

      [root@localhost ~]# netstat -na | grep 5005
      tcp        0      0 0.0.0.0:5005            0.0.0.0:*               LISTEN
      
    • 如果想知道本地客户端能不能连接远程的端口号,可以在本地客户端输入以下命令:

      ssh -v -p 5005 192.168.0.100

      以笔者在 Windows 的 CMD 中,访问 Linux 的端口号 5005 为例。

      如果访问成功,输出信息为:

      C:\Users\XXXXX>ssh -v -p 5005 192.168.0.100
      OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
      debug1: Connecting to 192.168.0.100 [192.168.0.100] port 5005.
      debug1: Connection established.
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_rsa type 0
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_rsa-cert type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_dsa type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_dsa-cert type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_ecdsa type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_ecdsa-cert type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_ed25519 type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_ed25519-cert type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_xmss type -1
      debug1: key_load_public: No such file or directory
      debug1: identity file C:\\Users\\XXXXX/.ssh/id_xmss-cert type -1
      debug1: Local version string SSH-2.0-OpenSSH_for_Windows_7.7
      ssh_exchange_identification: read: Connection reset
      

      如果访问不成功,输出信息为:

      C:\Users\XXXXX>ssh -v -p 5005 192.168.0.100
      OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
      debug1: Connecting to 192.168.0.100 [192.168.0.100] port 5005.
      debug1: connect to address 192.168.0.100 port 5005: Connection refused
      ssh: connect to host 192.168.0.100 port 5005: Connection refused
      
    • 如果本地 IntelliJ IDEA 中没有使用前述的 在文本上一致 的代码,而其它正确,则远程调试会成功,但断点会打不了(断点不生效)。

在 IntelliJ IDEA 中远程调试 Java 程序相关推荐

  1. 使用JDB调试Java程序

    使用JDB调试Java程序 1.使用JDK的JDB工具附加调试Java程序 首先用以下命令启动Java程序: java -Xdebug -Xrunjdwp:transport=dt_socket,se ...

  2. gdb java,调用gdb来调试java程序

    错误没有这样的文件或目录,gdb 如果错误消息来自emacs,则表示未安装 gdb . 要解决此问题,请安装 gdb . 请注意 gdb 不是emacs的一部分,它是一个单独的程序 . 如果你得到一个 ...

  3. java ui调试_如何使用 IBM i System Debugger 调试 Java 程序

    当在 IBM i 上使用 Java 时,您可以使用 Qshell Interpreter 或者 CL 命令提供的 Java tools,在 Qshell 环境和 IBM i 环境上进行与 Java 开 ...

  4. eclipse远程调试Java程序

    远程调试tomcat服务 配置tomcat在catalina.sh中添加如下 CATALINA_OPTS="-server -Xdebug -Xnoagent -Djava.compiler ...

  5. jdb java_利用JDB附加调试JAVA程序 | 学步园

    之前有介绍用Eclipse远程调试JAVA程序,见Eclipse远程调试JAVA程序,但现场JAVA程序出现异常,又不能在现场真实环境装Eclipse来调试,所幸有JDB这个工具.此工具的常规用法不介 ...

  6. 怎么在eclipse中调试java程序?

    怎么在eclipse中调试java程序?关于这个问题我已经回答过很多次,但许多朋友可能还没有理解,本篇文章再来详细为大家解答一下怎么在eclipse中调试java程序?等相关问题,希望对大家有所帮助. ...

  7. 使用Eclipse开发和调试java程序

    刚刚学习Java不久,从C#到Java的语言跨度倒是没有多大,但是编译器从VS2013换成Eclipse,最开始还是有些许的不适应.因此做个笔记跟和我一样的初学者分享一下经验. 下面简单介绍一下Ecl ...

  8. myeclipse怎么调试java,如何用MyEclipse调试JAVA程序

    如何用MyEclipse调试JAVA程序 1.在你觉得有错的地方设置断点 2.点击甲壳虫一样的按钮下面的子按钮,也是甲壳虫一样的,叫Debug 3.运行程序,当程序运行到刚才设置断点的位置就会停下来, ...

  9. 如何使用vscode安装和调试Java程序

    步骤一:安装调试 Vscode官方出的安装指南 步骤二:运行Java程序 需要注意的是,Java程序不能单独运行(就是单独写一个文件然后运行),要在项目里才可以运行起来. 运行时注意事项和可能出现的问 ...

最新文章

  1. excel调用python编程-用Python如何开发Excel宏脚本?新手必学
  2. 零基础可以学python吗-对于几乎是零基础的人,直接学 Python 编程合适吗?
  3. python3.6安装-Linux安装python3.6
  4. java集合框架的结构_集合框架(Collections Framework)详解及代码示例
  5. zune自搭虚拟服务器离线升级,Zune 30g 固件更新至 3.3 记录
  6. java 排队实现_实验排队功能实现(JAVA)
  7. linux git 显示 分支,Linux 终端显示 Git 当前所在分支
  8. AOP jdk动态代理
  9. 获得CPU利用率(python调用top命令实现)
  10. C#打造一个开源webgis(四)地图客户端(中)
  11. 计算机启动硬盘响,电脑开机时硬盘响个不停的原因及解决方法
  12. React Native常用三方组件库大全
  13. c++小游戏大全(不定时更新)
  14. MIP 和 MinIP
  15. fork和lockf应用
  16. 摩斯密码php,普及一下LOL中的摩斯密码 绝对的干货
  17. 我在CSDN学python-8
  18. windows无法验证发行者
  19. 拒绝了对对象 '表名' (数据库 '数据库名',架构 'dbo')的 SELECT 权限
  20. python网络爬虫之初识网络爬虫

热门文章

  1. where 1=1和 0=1 的作用
  2. JavaScript强化教程——JavaScript Math(算数) 对象
  3. codeforces 356C Bear and Square Grid
  4. Hive Join Strategies hive的连接策略
  5. Linux下的磁盘加密LUKS
  6. 学习腾讯的产品管理之道
  7. 批处理判断文件夹是否存在
  8. java压缩----使用ANT JDK压缩---只压缩选中目录的指定文件夹
  9. win10:JDK12.0.1环境变量配置
  10. linux 权限属性,linux 文件或目录的权限和属性