This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f2a18140e53a933f889efa71ae34d08f568c028c Author: opencode <[email protected]> AuthorDate: Mon Oct 19 12:04:57 2026 +0200 Record JSP usage time on every request, fixing premature idle unload JspServletWrapper.service() only advanced the wrapper's lastUsageTime when it was older than the timestamp of the previous background checkUnload() run, a gate introduced to limit jspQueue re-ordering to a single move per background cycle. When the jspIdleTimeout feature was added it reused the same gate for lastUsageTime, so the timestamp of an actively requested JSP advanced at most once per background processor cycle (default 10s). With jspIdleTimeout shorter than that cycle, JspRuntimeContext.checkUnload() saw continuously used JSPs as idle and unloaded them repeatedly, forcing needless recompilation and class loader churn; the LRU queue ordering was likewise stale by up to one cycle. Keep the once-per-cycle throttle for the makeYoungest() queue re-ordering, which was its original purpose (commit ee86d455a5), but record lastUsageTime unconditionally inside the already held wrapper lock, so the idle timeout check always sees the true last usage. Found by code review. --- java/org/apache/jasper/servlet/JspServletWrapper.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/java/org/apache/jasper/servlet/JspServletWrapper.java b/java/org/apache/jasper/servlet/JspServletWrapper.java index ff7dc8ee2e..7fe86af467 100644 --- a/java/org/apache/jasper/servlet/JspServletWrapper.java +++ b/java/org/apache/jasper/servlet/JspServletWrapper.java @@ -486,14 +486,15 @@ public class JspServletWrapper { if (unloadHandle == null) { unloadHandle = ctxt.getRuntimeContext().push(this); } else if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) { + // Limit queue re-ordering to a single move per + // background checkUnload() cycle. ctxt.getRuntimeContext().makeYoungest(unloadHandle); - lastUsageTime = System.currentTimeMillis(); - } - } else { - if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) { - lastUsageTime = System.currentTimeMillis(); } } + // Always record the usage time, so an actively used JSP is + // never seen as idle by checkUnload(), independent of how + // often the queue order above was updated. + lastUsageTime = System.currentTimeMillis(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
