如何确定是不是启用了“调试模式”

Posted

技术标签:

【中文标题】如何确定是不是启用了“调试模式”【英文标题】:How to find out if "debug mode" is enabled如何确定是否启用了“调试模式” 【发布时间】:2011-04-16 03:04:08 【问题描述】:

Java 程序如何确定它是否在调试模式下运行?

应用程序在常规“全速”模式下的行为应该与“调试模式”(连接调试器时,在调试模式下运行时)略有不同。应用程序通过 TCP 与另一台计算机、另一个进程或在其内部进行通信。我的同事希望我们默认使用 Socket.setSoTimeout(1000),以便从套接字读取最多可以阻塞 1 秒。在调试时,这当然是不够的,应用程序会停止正常工作。因此,解决方案是将SO_TIMEOUT 设置得更高,但只是处于调试模式(例如:无限制)。现在,我并不总是设置断点,也不想使用我可以自己设置“调试”属性的调试版本。有时我会附加调试器(远程调试)。我主要使用 Eclipse,所以一个可以在那里工作的解决方案就可以了。

可能的答案包括:

    要查看是否在调试模式下运行,请在java.lang.management.*javax.management.* 中使用以下方法...

    您的同事因 X 原因出错,您不应将 SO_TIMEOUT 默认设置为 1 秒。

更新

我知道系统属性方法,但我将问题留待解决以解决我最初的问题。

【问题讨论】:

@will 您对“调试模式”的定义与我的定义不符,而且您有一个非常不同的用例。在您的情况下,我假设使用配置设置(系统属性或其他)就可以了。对于我的用例,它不是。 既然你显然不是编程的初学者,我只是想知道你为什么试图避免使用系统属性方法,因为你肯定知道这将是最面向未来和最灵活的解决方案?跨度> @thehandofNOD 系统属性方法适用于某些用例,但不太方便。我一直在寻找一种自动化的方法。从对答案的投票中可以看出,许多其他人也对采用自动化方式感兴趣。 【参考方案1】:

我现在自己发现了:

boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean().
    getInputArguments().toString().indexOf("jdwp") >= 0;

这将检查是否使用了Java Debug Wire Protocol 代理。

【讨论】:

当然,这行得通,但这与与程序没有任何关系的东西紧密耦合。 这是一个 hack,因为没有官方 API 可以确定是否在调试模式下运行。系统属性会很好。但在上述情况下,程序应该在调试模式下表现不同。这完全是故意的。我只是不想在调试时手动设置系统属性。 @RobAu 所以可能它应该是indexOf("jdwp") >= 0,以匹配-agentlib:jdwprunjdwp。我会改变我的答案。 好答案。 contains("jdwp") 会比 indexOf("jdwp") >= 0 更具可读性。 Java 8:java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().stream().anyMatch(s -> s.contains("jdwp"))【参考方案2】:

使超时可配置。最简单的方法是只使用系统属性并使用Integer.getInteger 读取它:

private final static int SOCKET_TIMEOUT =
  Integer.getInteger("com.yourapp.module.socketTimeout", 1000); // default 1 sec

然后,在启动您的应用程序进行调试时,只需从命令行(或适当的配置文件,取决于您的应用程序运行的环境)设置属性:

java -Dcom.yourapp.module.socketTimeout=1000000 MainClass

这很好,因为当您在调试器中启动应用程序时,它不会神奇地改变行为,并且您可以在不调试时更改超时(例如,如果您需要在连接速度较慢的地方运行它,一些天)。

(当然,如果您的系统已经使用了一个配置文件,那么将这个值作为一个条目添加到那里可能是合适的。)

至于一秒是否是适当的超时......这完全取决于应用程序。有时最好最终给出一个正确的答案,有时快速失败比等待成功要好。

【讨论】:

Integer.getInteger(..)?该死,我不知道那个。酷(+1) 这当然是一个有效的解决方案,但它需要一个手动步骤:在启动时设置系统属性。我想避免这种情况。 @ThomasMueller 如果在调试模式下运行,只需设置com.yourapp.debug=true 系统属性并让您的应用程序检查它。如果它是默认值,那么您没有在调试模式下运行。这可以在 Eclipse Debug 配置中完成,这意味着您无需在每次要调试程序时都输入它。 @ThomasMueller 但是,无论您想调试应用程序多少次,您只需要执行一次。 *每台机器一次。如果您有多个开发人员,使用多个 IDE,那么这里仍然非常值得不手动执行步骤,imo。【参考方案3】:

你解决了错误的问题。您的程序不需要知道这一点,除非它正在处理 eclipse 或 jvm 内部。

解决方案

使用具有默认值的系统属性:

int timeout = Integer.parseInt( 
    System.getProperty("socket.timeout", "1000"));
socket.setSoTimeout(timeout);

而在调试启动配置中,只需添加

-Dsocket.timeout=20000

到调用参数

(如果不指定系统属性,将使用默认值)

参考文献

System Properties阳光版块 Java 教程 System.getProperty(prop, def)javadocs

【讨论】:

这里也一样:我想避免手动设置系统属性。

以上是关于如何确定是不是启用了“调试模式”的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本调试方法

错误只出现在发布模式而不是调试模式

在调试模式下运行程序非常慢

C编译器中是不是有调试模式编译标志的标准?

安卓系统如何打开USB调试模式

具有捆绑和缩小功能的 ASP.NET MVC 4 应用程序,为啥在调试模式下启用缩小?