使用 Cpolar + Remote JVM Debug 进行内网服务器调试
liuian 2025-09-01 08:14 5 浏览
前言
在公司测试环境中,许多服务部署在内网,无法直接从公网访问。假设内网服务器运行的某个 JAR 文件发生异常(如挂掉或接口无法访问),你可以通过 cpolar 配合远程 JVM 调试来在家里通过 IDEA 调试该 JAR 文件。通过内网穿透技术,你可以远程连接到测试环境并进行调试。
本文使用的示例项目已在GitHub开源,您可以直接获取完整代码进行学习和实践:
- 项目特点:基于Spring Boot的远程调试测试项目,包含正常接口和异常接口,便于测试各种调试场景
1. Remote JVM Debug
Remote JVM Debug(远程JVM调试)是一种允许开发人员通过调试工具(如 IntelliJ IDEA)连接到运行在远程服务器上的Java应用程序并进行调试的技术。这个过程通常涉及通过网络连接到远程JVM实例,并允许开发者在不直接访问物理机器的情况下查看、修改代码状态,诊断和修复问题。
2. 系统要求与环境准备
2.1 服务器环境
- 内网服务器操作系统:Windows 或 Linux。
- JDK 版本:确保服务器上安装了正确版本的 JDK,支持远程调试。
- cpolar 安装:需要在内网服务器上安装 cpolar 客户端,用于穿透远程登录、调试端口及HTTP请求。
2.2 本地开发环境
- IDEA:本地开发机器需要安装 IntelliJ IDEA。
- JDK:本地开发机器需要安装 JDK(版本与远程服务器相同)。
3. 内网服务器准备及开始
由于大部分项目基本部署在Linux服务器中,因为Linux的性能更优,占用更低。所以本文采用的模拟内网服务器为Linux的CentOS7系统。
3.1 安装cpolar配置支持远程ssh登录
此步骤需提前在内网服务器中操作,以支持在家远程登录公司测试环境中的内网服务器
3.1.1 什么是cpolar?
- cpolar 是一款内网穿透工具,可以将你在局域网内运行的服务(如本地 Web 服务器、SSH、远程桌面等)通过一条安全加密的中间隧道映射至公网,让外部设备无需配置路由器即可访问。
- 广泛支持 Windows、macOS、Linux、树莓派、群晖 NAS 等平台,并提供一键安装脚本方便部署。
3.1.2 安装cpolar
首先,我们需要先安装curl:
sudo yum install curl
接下来下载cpolar,一条命令完成安装
curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash
测试cpolar版本以确保安装
cploar version
3.1.3 注册及配置cpolar系统服务
官网地址:https://www.cpolar.com
进入cpolar官网,点击免费注册按钮进行注册一个账号
向系统添加及启动cpolar服务
#添加cpolar服务
sudo systemctl enable cpolar
#启动cpolar服务
sudo systemctl start cpolar
查看服务状态
sudo systemctl status cpolar
3.1.4 登录cpolar web ui 管理界面配置ssh端口穿透
3.1.4.1 放行9200端口
在访问web页面前,需要先检查系统防火墙是否放行9200端口,避免访问不了
systemctl status firewalld
有两种方式可以实现访问,一种是放行该端口,另一种是直接关闭防火墙(不建议)
#放行 9200 端口
#--zone=public:使用默认区域(通常是 public)
#--add-port=9200/tcp:添加 TCP 协议的 9200 端口
#--permanent:永久生效(不加此参数则是临时规则,重启失效)
firewall-cmd --zone=public --add-port=9200/tcp --permanent
#重载防火墙配置(及刷新配置使其生效)
firewall-cmd --reload
验证端口是否已放行
firewall-cmd --zone=public --query-port=9200/tcp
输出内容为yes则成功放行
3.1.4.2 访问cpolar web ui管理界面
在访问之前,不确定ip地址可以通过ifconfig命令查看服务器ip
ifconfig
确定好ip地址后,在浏览器中访问:
http://<此处应为您的IP>:9200 #如:http://192.168.184.133:9200
将前面步骤注册好的cpolar账号登录即可进入后台页面
登录成功同时,服务器也会后台无感自动配置token,无需手动配置token
配置文件位置:
/usr/local/etc/cpolar/cpolar.yml
cat /usr/local/etc/cpolar/cpolar.yml
3.1.4.3 保留固定TCP公网地址
使用cpolar为其配置TCP地址,该地址为固定地址,不会随机变化,方便后续ssh远程登录。
进入官网的预留页面:
https://dashboard.cpolar.com/reserved
列表中显示了一条已保留的TCP地址记录:
- 地区:显示为China Top。
- 地址:显示为16.tcp.cpolar.top:14290。
注:地址每个账号的都不同,请以自己保留生成的为主
3.1.4.4 启用ssh隧道,配置固定tcp地址
点击左侧菜单栏的隧道管理,展开进入隧道列表页面,页面下默认会有 2 个隧道:
- ssh隧道,指向22端口,tcp协议
- website隧道,指向8080端口,http协议(http协议默认会生成2个公网地址,一个是http,另一个https,免去配置ssl证书的繁琐步骤)
接着点击ssh隧道的编辑按钮,进入编辑页面,修改成固定tcp地址,如图所示:
3.1.4.5 使用固定的tcp地址进行远程ssh登录
ssh远程工具可以使用MobaXterm、Xshell或者FinalShell都可以,这里采用FinalShell进行远程登录演示
接下来,双击创建的ssh连接,如出现提示,点击接受并保存即可,即可连接到内网服务器
3.2 安装JDK
本文采用jdk17作为演示
#下载jdk17软件包
wget https://download.oracle.com/java/17/archive/jdk-17_linux-x64_bin.rpm
#安装jdk17
sudo rpm -ivh jdk-17_linux-x64_bin.rpm
安装完成后,查看版本,确认安装
java -version
3.3 上传打包好的Jar文件至服务器
该项目为简单模拟测试调试使用项目,共写3个简单接口:
- 正常接口:/api/normal/info:获取应用程序的基本信息,包括名称、版本、作者等
- 异常接口:/api/bug/null-pointer:故意抛出NullPointerException,用于调试异常处理
- 阻塞接口:/api/bug/infinite-loop:进入无限循环,模拟线程阻塞场景
3.3.1 打包springboot项目
idea中侧边栏选择Maven选项,然后如图操作进行构建打包jar文件:
3.3.2 上传至服务器
依次步骤打开找到jar文件
springboot-debug-test-1.0.0.jar
将jar文件直接拖动至finalshell空白处即可上传
注意:一定要使用 root 用户登录,否则上传可能失败(或者确保当前用户对目标目录具有写权限)。
如果使用普通用户登录 FinalShell,可通过 chmod 或 chown 命令赋予目标目录写权限。
4. 启动 JAR 文件并配置远程调试
4.1 启动 JAR 文件
使用 java -jar 命令启动你需要调试的 JAR 文件,并开启远程调试。需要在启动命令中指定 JVM 调试参数:
java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 springboot-debug-test-1.0.0.jar
5005 为远程调试的端口号。
springboot-debug-test-1.0.0.jar 是要调试的 JAR 文件名称。
项目已经成功启动,端口5005被监听,后台该jar文件项目在端口8080(http)上运行。
4.2 cpolar隧道配置
4.2.1 http(8080端口)穿透
访问cpolar web ui管理界面(忘记可看前面3.1.4.2小节),进入到隧道列表,名称为website的隧道,点击编辑,可以看到如下信息:
- 隧道名称:website
- 协议:http
- 本地地址:8080
这些信息正是后台项目8080端口所需要的,所以不需要进行修改,默认创建好的隧道直接可以使用。
接着左侧菜单栏选择【状态】>【在线隧道列表】,可以看到website隧道有两个公网地址,http协议(http协议默认会生成2个公网地址,一个是http,另一个https,免去配置ssl证书的繁琐步骤)
直接选择一个至浏览器测试,这里选择http(注:每个用户的公网地址都不相同)
由于后台项目提到的接口地址后缀为/api/normal/info,所以正确拼接地址应为:
<您的公网地址>/api/normal/info #如:http://5c19bf20.r1.cpolar.top/api/normal/info
接口正常返回了api接口信息,穿透成功!
4.2.2 调试端口(5005端口)穿透
4.2.2.1 保留固定tcp地址
选择将5005端口穿透设置为固定的tcp地址是为了方便后续多次调试,tcp地址不会进行变化,也可以不进行此步骤操作。
进入官网的预留页面:
https://dashboard.cpolar.com/reserved
- 地区当前选择的是:China Top
- 地址信息为:3.tcp.cpolar.top:12718
记住新创建的地址信息(注意:每个用户创建的地址信息都有所不同,请注意个人的地址信息)
4.2.2.2 创建新隧道
进入创建隧道列表,填写好对应信息,如下图:
- 协议:tcp
- 本地地址为:5005
- 端口类型:固定tcp端口
- 预留tcp地址:填写您预留固定的tcp地址
5.IDEA远程Debug调试内网项目
5.1 idea配置remote jvm debug
点击启动按钮左边的选项卡,然后在选项卡中点击Edit Configurations进入Run/Debug Configurations页面
依次点击左上角【+】号按钮,下滑选择【Remote JVM Debug】选项,点击进入。
填写主机以及端口信息,具体参考如下图:
- Name:自定义名字(如:Remote Debug)
- Host:填写固定的tcp地址去除端口部分(如:3.tcp.cpolar.top)
- Port:填写固定的tcp地址端口部分(如:12718)
5.2 启动及调试
点击右上角的小虫子图标即可启动调试,启动调试后,控制台会出现类似Connected to the target VM, address: '3.tcp.cpolar.top:12718', transport: 'socket'的信息,即代表启动成功
来到BugController控制器,里面有一个异常接口api/bug/null-pointer,代码如下:
/**
* 空指针异常接口
*
* 该接口会故意抛出NullPointerException
* 用于测试空指针异常的调试场景
*
* @return 永远不会执行到这里,因为会抛出异常
*/
@GetMapping("/null-pointer")
public String nullPointerException() {
//1.此位置故意设置nullString字符串为null
String nullString = null;
String now = LocalDateTime.now().format(FORMATTER);
System.out.println("空指针异常接口被调用,准备抛出异常,时间:" + now);
//2.待接口返回时执行nullString的toString方法时就会抛出NullPointerException异常
return nullString.toString();
}
切换到浏览器,然后请求8080端口的穿透地址+异常接口地址进行请求,如:
<您的8080端口穿透地址>/api/bug/null-pointer #如:http://5c19bf20.r1.cpolar.top/api/bug/null-pointer
接着在String nullString = null;代码段左边打上断点调试,如下图:
再次请求一次该链接
http://5c19bf20.r1.cpolar.top/api/bug/null-pointer进行发送http请求,可以看到后端idea中已经进去断点调试了
进入下一步骤,查看到nullString变量值确实为null
多跳几个步骤,进入源码后可以确认已抛出空指针异常,提示 nullString 为 null,无法调用其方法。
在finalShell终端1界面中也可以看到,控制台输出的日志出现了NullPointerException异常
通过以上的配置,这样您就可以在家中或者外出无法及时回到公司时,也能很轻松的调试公司中内网服务器里部署的测试环境项目啦!
6.可能出现的问题
6.1 访问页面出现404的情况是怎么回事?
访问出现404:
可以发现,接口路径中少了全局上下文路径/api ,补上就可以访问啦!
7.总结
通过本教程,我们成功实现了使用 Cpolar 结合 Remote JVM Debug 技术,在本地 IDE 环境中调试部署在公司内网中的 Java 服务。整体流程包括:
- 安装并配置 Cpolar,打通从公网访问内网的通道;
- 启用 JVM 的远程调试模式,开放调试端口;
- 使用 IntelliJ IDEA 配置 Debug 远程连接;
- 最终实现对远程服务的断点调试与问题排查。
本方案适用于以下典型场景:
- 公司测试环境无法直接从公网访问;
- 无法通过 VPN 连通或 VPN 配置复杂;
- 出现远程服务异常但又难以复现时,进行现场调试。
在实际使用中应注意:
- 远程调试存在安全风险,建议仅限于测试环境,并设置好访问权限;
- cpolar 每次生成的公网地址可能会变化,建议使用固定子域名(需高级用户);
- 远程调试应避免在生产环境开启,以免暴露调试端口。
通过这种方式,极大提升了远程问题定位效率,也为远程办公/故障应急提供了可靠手段。
以上就是如何在本地使用Remote JVM Debug 进行内网服务器调试,并安装cpolar内网穿透工具配置固定不变的TCP公网地址,实现随时随地远程访问的全过程,感谢您的观看,有任何问题欢迎留言交流。
相关推荐
- C语言学习从内存堆栈视角,给这段枚举代码做个 "内存透视"
-
从内存堆栈视角,给这段枚举代码做个"内存透视"#include<stdio.h>enumDAY{MON=1,TUE,WED,THU,FR...
- Python基础:枚举,都有哪些特点和使用场景呢?
-
在Python编程语言中,枚举(Enumeration)是一种特殊的类,用于为一组常量创建一个名称空间。枚举类在Python3.4中被引入,提供了一种更加直观和方便的方式来处理一组相关的常量。枚举类...
- Java枚举你真的会用吗_java枚举怎么使用
-
概述Java中枚举,大家在项目中经常使用吧,主要用来定义一些固定值,在一个有限的集合内,比如在表示一周的某一天,一年中的四季等。那你了解枚举的本质吗?了解枚举的一些常见用法吗?枚举介绍和使用枚举主要用...
- 反射、枚举以及Lambda表达式_反射getmethod
-
一、反射1.定义Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法(即使是私有的);对于任意一个对象,都能够调用它的任意方法和属性,那么,我们就...
- 一个高效使用cursor开发项目的方法,怎么让 AI 写的代码不跑题?
-
最近又用cursor做了一个小应用,番茄时钟,用来管理自己的时间,提高效率。然后使用cursor开发的过程中。有了一些新的感悟。找到了一条可以让Curosr不跑题的办法。生成一份详细的项目资...
- 前端铜九铁十面试必备八股文——工程化
-
常用的git命令gitclone:克隆远程仓库到本地。gitinit:在当前目录初始化一个新的Git仓库。gitadd:将文件添加到暂存区,准备提交。gitcommit-m"co...
- IntelliJ IDEA 2025.2 的主要更新亮点
-
以下是该版本的一些关键改进与功能更新:AI增强体验离线Java代码补全:AI助手现在支持在离线模式下进行Java代码块建议,并允许用户选择本地代码模型使用。AIAssistant新增...
- 一行命令,AI 直接写代码!OpenAI 正式发布 Codex CLI
-
【一句话速读】OpenAI把2021年的Codex品牌复活,推出全新CodexCLI——一个本地运行的轻量级编码代理。只需npmi-g@openai/codex,它就能在终端里帮...
- 如何使用高级TypeScript模式构建可扩展的QA框架
-
TypeScript自动化QA(7部分系列)TypeScript第一步:自动化QA实用路线图如何在TypeScript中使用数组和对象构建强大的QA自动化脚本如何掌握TypeScript基础...
- Bun JS工具包新增MySQL驱动和密钥管理功能
-
Bun团队发布了其JavaScript打包器和运行时的1.2.21版本,该工具使用Zig语言编写,新增了包括MySQL和SQLite内置驱动、YAML解析器以及用于工具和本地开发的密钥管理器等功能。新...
- 编码 10000 个小时后,开发者悟了:“不要急于发布!”
-
【CSDN编者按】在软件开发的道路上,时间是最好的老师。根据“一万小时定律”,要成为某个领域的专家,通常需要大约一万小时的刻意练习。本文作者身为一名程序员,也经历了一万小时的编程,最终悟出了一个道理...
- 一文说明,TypeScript 的装饰器_typescript logo
-
●装饰器(Decorators)●注意:装饰器目前是一项实验性特性,在未来的版本中可能会发生改变●装饰器一般使用在以下几个地方○类○类属性○类方法○类方法的参数○通过这些我们也能看得出来,...
- 前端小哥哥:如何使用typescript开发实战项目?
-
前言笔者上一篇文章:主要写了typescript的用法和核心知识点总结,这篇文章将通过一个实际的前端案例来教大家如何在项目中使用typescript.你将收获如何使用umi快速搭建一个基于React...
- 一篇文章搞懂TypeScript_typescript implements
-
TypeScript是JavaScript的超集,一方面给动态类型的js增加了类型校验,另一方面扩展了js的各种功能。原始数据类型字符串数值布尔nullundefinedSymbolBi...
- TypeScript的any和unknown,用错一个就是线上Bug
-
在TypeScript开发中,类型系统是我们抵御运行时错误的第一道防线。但两个特殊类型——any和unknown,却常常被误用,成为线上故障的隐形推手。本文通过真实案例解析,告诉你为什么unknown...
- 一周热门
-
-
【验证码逆向专栏】vaptcha 手势验证码逆向分析
-
Python实现人事自动打卡,再也不会被批评
-
Psutil + Flask + Pyecharts + Bootstrap 开发动态可视化系统监控
-
一个解决支持HTML/CSS/JS网页转PDF(高质量)的终极解决方案
-
再见Swagger UI 国人开源了一款超好用的 API 文档生成框架,真香
-
网页转成pdf文件的经验分享 网页转成pdf文件的经验分享怎么弄
-
C++ std::vector 简介
-
飞牛OS入门安装遇到问题,如何解决?
-
系统C盘清理:微信PC端文件清理,扩大C盘可用空间步骤
-
10款高性能NAS丨双十一必看,轻松搞定虚拟机、Docker、软路由
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)