如何确定是不是启用了“调试模式”
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:jdwp
和runjdwp
。我会改变我的答案。
好答案。 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【讨论】:
这里也一样:我想避免手动设置系统属性。以上是关于如何确定是不是启用了“调试模式”的主要内容,如果未能解决你的问题,请参考以下文章