在我的应用程序中,如果不确定是否在合理的时间内满足条件,我会使用超时退出某些无限循环。
为了计时,我使用系统的时间,因为它很简单:
public class BenchmarkTimer
{
private long startTime;
public BenchmarkTimer()
{
startTime = System.currentTimeMillis();
}
public boolean isExpired(long milliseconds)
{
long executionTime = currentTimeMillis() - startTime;
return executionTime > milliseconds;
}
}
然而,在调试时,我不希望在应用程序冻结时继续时间。这显然不会默认工作,因为即使在断点期间系统时间也会继续。由于我在断点上花了很长时间才能继续,因此我不想进入超时状态,因为在正常的应用程序执行情况下,这会有不同的行为(例如,它会在#34之前执行更多尝试;放弃")
这个问题有什么解决方案吗? IntelliJ IDEA
只能在断点期间暂停Java应用程序可见的系统时间吗?我希望调试的行为类似于常规执行,包括超时,因此我不确定如何实现这一点。
答案 0 :(得分:0)
Ran评论的链接给了我正确的想法:
运行一个线程,如果Thread.sleep()
睡得足够短,就会一直检查,否则事情很可疑,我们可能会遇到断点,所以我们可以“阻止”时钟,并在再次请求系统时间时返回更旧的时间
import lombok.val;
import static com.mycompany.SystemTimeBreakpointFixer.getCurrentTimeMillis;
import static com.mycompany.SystemTimeBreakpointFixer.considerRunningTimerFixerThread;
import static java.lang.System.currentTimeMillis;
import static java.lang.management.ManagementFactory.getRuntimeMXBean;
public class BenchmarkTimer
{
private long startTime;
static
{
considerRunningTimerFixerThread();
}
public BenchmarkTimer()
{
startTime = getCurrentTimeMillis();
}
public boolean isExpired(long milliseconds)
{
val currentTimeMillis = getCurrentTimeMillis();
val executionTime = currentTimeMillis - startTime;
return executionTime > milliseconds;
}
static class SystemTimeBreakpointFixer
{
private static final String THREAD_NAME = "System Time Fixer";
private static final int CHECKING_DELAY = 100;
private static final int NON_BREAKPOINT_DELAY = 100;
private static final String DEBUGGING_INPUT_ARGUMENT = "-agentlib:jdwp";
private static final boolean ARE_WE_DEBUGGING;
static
{
ARE_WE_DEBUGGING = areWeDebugging();
}
private static boolean areWeDebugging()
{
val runtimeMXBean = getRuntimeMXBean();
val inputArguments = runtimeMXBean.getInputArguments();
val jvmArguments = inputArguments.toString();
return jvmArguments.contains(DEBUGGING_INPUT_ARGUMENT);
}
private static long totalPausedTime = 0;
private static Thread thread;
static long getCurrentTimeMillis()
{
sleepThread();
val currentTimeMillis = currentTimeMillis();
return currentTimeMillis - totalPausedTime;
}
static void considerRunningTimerFixerThread()
{
if (ARE_WE_DEBUGGING && thread == null)
{
startTimerFixerThread();
}
}
private static void startTimerFixerThread()
{
thread = new Thread(() ->
{
//noinspection InfiniteLoopStatement
while (true)
{
val currentMilliseconds = currentTimeMillis();
sleepThread();
val updatedMilliseconds = currentTimeMillis();
val currentPausedTime = updatedMilliseconds - currentMilliseconds - CHECKING_DELAY;
if (currentPausedTime > NON_BREAKPOINT_DELAY)
{
totalPausedTime += currentPausedTime;
}
}
});
thread.setName(THREAD_NAME);
thread.start();
}
private static void sleepThread()
{
try
{
Thread.sleep(CHECKING_DELAY);
} catch (InterruptedException exception)
{
exception.printStackTrace();
}
}
}
}
还可以参考this文章了解调试器检测。
答案 1 :(得分:0)
在带有返回值的行的isExpired内部使用断点并设置:
executionTime = 0
现在处于调试模式,它将修改执行时间,以便isExpired始终返回false