Affects: 6.0.10


I was scheduling a task using @Scheduled(fixedDelay = Long.MAX_VALUE) in Spring version 6.0.9. The intention was to schedule the task only once. However, after upgrading to version 6.0.10, the application fails to start with the following exception:

java.lang.ArithmeticException: long overflow
    at java.base/java.lang.Math.multiplyExact(Math.java:1004)
    at java.base/java.time.Duration.toNanos(Duration.java:1250)
    at org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler.scheduleWithFixedDelay(ThreadPoolTaskScheduler.java:420)

It seems that the method ThreadPoolTaskScheduler.scheduleWithFixedDelay() was changed in commit 3415b04c7326e1d78dae92b8997fb9355aff6223, which is referenced by issue #30666. This change modifies the delay time unit from milliseconds to nanoseconds. I suspect that this alteration may be the cause of the exception.

Comment From: jhoeller

Technically, there was always a risk of an overflow there but previously you could only trigger that via fixedDelay = Long.MAX_VALUE, timeUnit = TimeUnit.SECONDS or the like, whereas now it can be triggered with the default milliseconds unit. We'll see what we can do about this, falling back to millisecond or even second precision when necessary.

Comment From: jhoeller

There is a more idiomatic solution: We can use JDK 11's long TimeUnit.convert(Duration) method which prevents arithmetic overflows, turning them into Long.MAX_VALUE instead. After all, such large values just mean arbitrary long out anyway, precision does not really matter there. Whereas for shorter delays and periods, nano precision is certainly beneficial.

Comment From: ipalbeniz

Thank you so much @jhoeller !

Comment From: cmuchinsky

@jhoeller I'm seeing a similar overflow exception coming from https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework/scheduling/concurrent/ReschedulingRunnable.java#L83, should the same fix be applied to that as well?