В моем приложении я использую тайм-ауты для выхода из определенных бесконечных циклов, если неясно, будет ли выполнено условие в разумные сроки.
Для хронометража я использую системное время, так как оно простое:
public class BenchmarkTimer
{
private long startTime;
public BenchmarkTimer()
{
startTime = System.currentTimeMillis();
}
public boolean isExpired(long milliseconds)
{
long executionTime = currentTimeMillis() - startTime;
return executionTime > milliseconds;
}
}
Однако при отладке я не хочу, чтобы время продолжалось, пока приложение зависло. Очевидно, что по умолчанию это не работает, поскольку системное время будет продолжаться даже во время точек останова. Я не хочу, чтобы у меня был тайм-аут из-за того, что я слишком долго использовал точку останова для продолжения, потому что при нормальном выполнении приложения это будет вести себя по-другому (например, оно выполнит больше попыток, прежде чем «сдаться»).
Есть ли какое-нибудь решение этой проблемы? Может ли IntelliJ IDEA останавливать системное время, видимое для приложения Java только во время точек останова? Я хочу, чтобы отладка вела себя как обычное выполнение, включая таймауты, поэтому я не уверен, как это сделать в целом.




Ссылка, прокомментированная Побежал, дала мне правильное представление:
Запустите поток, который постоянно проверяет, достаточно ли долго спал 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();
}
}
}
}
Также кредиты статье это для обнаружения отладчика.
используйте точку останова внутри isExpired в строке с возвратом с настройками:
executionTime = 0Теперь в режиме отладки он изменит ExecutionTime, чтобы isExpired всегда возвращал false.
Похоже, это должно быть полезно. stackoverflow.com/a/39399216/3655191