This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit fa2825827f3d0c630acc361eeb349970820d63a5 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 90d5cdfdc5..30a3f57d9a 100644 --- a/java/org/apache/jasper/servlet/JspServletWrapper.java +++ b/java/org/apache/jasper/servlet/JspServletWrapper.java @@ -483,14 +483,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]
