一、前言
有时候我们需要远程debug服务器上的服务,因为有些问题在某些环境才会复现。那我们应该怎么做呢?怎么模拟呢?
可以打印本机ip的形式,来判断远程debug是否成功。
二、编写demo程序
先看看我的本机IP
1、获取本机IP的坑
编写打印本机IP的程序,但是下面这段程序真的是本机真实Ip吗?其实不是的。
这种方式获取的主机名没啥问题,但获取到的IP地址却有待考量,如果一台机器有多个网卡如何远程调试应用程序,他获取的IP是谁的呢?
try {
InetAddress address = InetAddress.getLocalHost();
System.out.println(address.getHostName());
System.out.println(address.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
输出:
LAPTOP-7TIN112S
192.168.223.1
2、获取本机真实的IP
从JDK1.4开始,提供 NetworkInterface 类。这个类可以得到本机所有的物理网络接口和虚拟机等软件利用本机的物理网络接口创建的逻辑网络接口的信息。
package com.abao.demo;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;
/**
* @author:yl
* @date:2021-05-10 21:54:54:34
* @description:
*/
public class Demo {
public static void main(String[] args) {
String ip = "";
try {
if (isWindowsOS()) {
ip = getWindownsIp();
} else {
ip = getLinuxIp();
}
} catch (SocketException e) {
e.printStackTrace();
}
System.out.println(ip);
}
private static boolean isWindowsOS() {
String osName = System.getProperty("os.name");
return osName.toLowerCase().contains("windows");
}
private static String getWindownsIp() throws SocketException {
String msg = "";
Enumeration faces = NetworkInterface.getNetworkInterfaces();
while (faces.hasMoreElements()) { // 遍历网络接口
NetworkInterface face = faces.nextElement();
if (face.isLoopback() || face.isVirtual() || !face.isUp()) {
continue;
}
//Windows 平台上局域网的网络接口以“wlan”开头。(lo 为本地回环地址,eth0 和 eth4 为 VMware 创建的虚拟地址)
if (face.getName().startsWith("wlan")) {
System.out.print("网络接口名:" + face.getName() + ",地址:");
Enumeration address = face.getInetAddresses();
while (address.hasMoreElements()) { // 遍历网络地址
InetAddress addr = address.nextElement();
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress() && !addr.isAnyLocalAddress()) {
msg = addr.getHostAddress() + " ";
}
}
}
}
return msg;
}
private static String getLinuxIp() throws SocketException {
String msg = "";
for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
String name = intf.getName();
if (!name.contains("ens33")) {
continue;
}
for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.getHostAddress().contains("fe80"))
msg = "网络接口名:" + name + ",地址:" + inetAddress.getHostAddress();
}
}
return msg;
}
}
windowns结果:
linux结果:
三、远程debug步骤1、改造上面打印IP的代码
死循环是为了不让程序停止启用本机代码调试如何远程调试应用程序,否则怎么debug?
public static void main(String[] args) {
System.out.println("start debug ");
new Thread(() -> {
while (true) {
String ip = "";
try {
if (isWindowsOS()) {
ip = getWindownsIp();
} else {
ip = getLinuxIp();
}
} catch (SocketException e) {
e.printStackTrace();
}
System.out.println(ip);//在这里打断点
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
2、设置jvm参数
注意开放服务器5005端口
启动的时候加入:
java -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y -jar demo-1.0-SNAPSHOT.jar
-Xdebug:通知JVM工作在debug模式下;
-Xrunjdwp:通知JVM使用(java debug wire protocol)来运行调试环境;
transport:监听Socket端口连接方式
suspend=y表示启动时就进入调试模式,一般用于被动连接,因此我们客户端主动连接才会运行。
3、idea配置如下
添加路径:Intellij Idea界面的Run/Debug左边是配置运行的Edit Configuration,然后点击添加Remote运行环境的相关参数启用本机代码调试,参数示例如下图所示
4、结果
可以看到远程地址是我服务器的地址,远程调试配置成功。
四、注意点
留言评论