在Eclipse中确定Java应用程序是否处于调试模式

47

我希望可以根据调试需求更改日志记录级别,但是我找不到检查应用程序是否运行在调试模式下的代码片段。

我正在使用Eclipse来调试该应用程序,所以如果解决方案只适用于Eclipse也没问题。

7个回答

67

19
布尔变量isDebug的值取决于当前JVM进程是否使用了"-agentlib:jdwp"调试参数。该值由以下代码确定:java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("-agentlib:jdwp") - Frank Meulenaar
2
@FrankMeulenaar 这是非常特定于供应商的。只要你知道就没问题。 - Thorbjørn Ravn Andersen
3
请注意,一些调试器仍在使用旧的参数“-Xrunjdwp”,我已经编写了代码以查找两个JVM参数。 - bric3
1
boolean isDebug = ManagementFactory.getRuntimeMXBean().getInputArguments().stream().anyMatch(arg -> arg.startsWith("-agentlib:jdwp")) - Hakanai
在NetBeans 8.2中,调试器参数看起来像这样而不是“[-Xdebug,-Xrunjdwp:transport = dt_shmem,address = javadebug]”,需要对此字符串进行不同的检查。 - tobi delbruck
显示剩余2条评论

21

您可以修改调试配置。例如,只需在调试配置中添加特殊的 VM 参数。您可以使用 System.getProperties() 读取提供的参数。

更好的做法是修改配置文件(运行和调试)以加载不同的日志配置文件。如果需要编写代码确定日志级别,则不太好。这应该仅仅是一个配置问题。


8

在JVM内部,没有一种官方认可的可靠方法来确定任何给定的JVM是否处于调试模式,依赖于现有的工具只会在将来某个时候破坏您的代码。

因此,您需要自己引入一种方法。建议如下:

  • 系统属性。
  • 环境变量(类似于$HOME或% HOME%的shell变量)
  • 询问JVM关于给定资源的物理位置- http://www.exampledepot.com/egs/java.lang/ClassOrigin.html - 并根据其进行决策(路径是否包含单词“debug”? 它是在jar文件中还是未打包的类文件中?等等)。
  • JNDI
  • 特定资源的存在或内容。

1
有时候你并不关心未来的代码,你只需要能够立即调试它,并且正常情况下它也能正常工作。 - simpleuser
@user1663987 在任何情况下选择最合适的方法仍然需要您了解这些内容。请注意,启用调试(对于所有实际目的而言,对被调试的程序是不可见的)和更改日志配置之间存在巨大差异 - 这不是大多数程序员希望相互影响的事情。 - Thorbjørn Ravn Andersen

5
你尝试在Eclipse运行配置中添加VM参数吗?
将此作为VM参数传递。
-Ddebug=true

那么你可以使用Boolean.getBoolean("debug")来检查这个问题。


2
Boolean.getBoolean("debug") 是愚蠢的,因为它试图将字符串“debug”转换为布尔值,这总是导致false。 - Daniel
1
@Daniel,这是误导性的,因为JavaDocs关于此方法的说明是:仅当由参数命名的系统属性存在且等于字符串“true”时,才返回true。因此,只要设置了此属性,此解决方案就有效。 - Sebastian Götz

2
如果您想从自己的程序中设置调试级别,可以使用类似以下代码的语句:
public static final boolean DEBUG_MODE = System.getProperty("java.vm.info", "").contains("sharing");

这个技巧可以解决问题。

我在Eclipse 3.5中测试过:

package test;

public class Test
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println(System.getProperty("java.vm.info", ""));
    }

}

将显示:

mixed mode, sharing

如果没有启动调试模式

mixed mode

如果使用调试启动器执行


Joachim Sauer 评论:

这高度依赖于系统。
我假设“共享”表示跨VM类共享处于活动状态。
这是一个非常新的功能,只有在某些平台上才可用。
此外,可能有许多原因可以启用或禁用它,所以我不会将其用于调试模式检测。

(注意:我使用最新的jdk1.6b14进行了测试。我将其留作CW答案。)


1
这非常依赖于系统。我认为“共享”表示跨虚拟机类共享是活动的。这是一个非常新的功能,只在某些平台上可用。此外,启用或禁用它可能有许多可能的原因,因此我不会将其用于调试模式检测。 - Joachim Sauer
1
@Joachim:说得好(我这里使用的是最新的jdk 1.6b14)。我会更新我的答案并将其留作社区维基档案。 - VonC
依赖于一个为人类阅读而缩进的字符串属性的内容,最多也只是脆弱的。 - Thorbjørn Ravn Andersen
我已经在Windows 10上使用Oracle Java Hotspot jdk1.7.0和jdk1.8.0进行了测试,并且在调试和非调试模式下都得到了相同的“混合模式”字符串,就像gojomo在1.6 jdks中指出的那样。 - cleberz
@ThorbjørnRavnAndersen 好的。有没有针对JDK9特定的解决方案? - VonC
显示剩余3条评论

0

1
这是针对Eclipse平台/插件跟踪的,而不是普通调试。 - J-16 SDiZ

0
如果使用套接字(例如9999),您可以调用netstat来检查是否建立了连接:
Process p = new ProcessBuilder("netstat", "-n").start();
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());

然后在标准输出中扫描 127.0.0.1:9999.*ESTABLISHED


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接