This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 592bc75020 Refactor JreCompat for minimum Java version of Java 21
592bc75020 is described below

commit 592bc75020589df542320ae0a55cf7ff400bd45f
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu May 11 17:09:03 2023 +0100

    Refactor JreCompat for minimum Java version of Java 21
---
 java/org/apache/catalina/core/StandardContext.java |  20 ----
 .../catalina/loader/WebappClassLoaderBase.java     | 132 ++++++++++-----------
 .../org/apache/tomcat/util/compat/Jre19Compat.java |  84 -------------
 java/org/apache/tomcat/util/compat/JreCompat.java  |  80 +------------
 .../tomcat/util/compat/LocalStrings.properties     |  16 ---
 .../tomcat/util/compat/LocalStrings_fr.properties  |  16 ---
 .../tomcat/util/compat/LocalStrings_ja.properties  |  16 ---
 .../tomcat/util/compat/LocalStrings_ko.properties  |  16 ---
 .../util/compat/LocalStrings_zh_CN.properties      |  16 ---
 .../servlet/http/HttpServletDoHeadBaseTest.java    |  37 ++----
 webapps/docs/config/context.xml                    |  15 ---
 11 files changed, 81 insertions(+), 367 deletions(-)

diff --git a/java/org/apache/catalina/core/StandardContext.java 
b/java/org/apache/catalina/core/StandardContext.java
index 888aa53e0e..5d1cc905ad 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -705,12 +705,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
      */
     private boolean renewThreadsWhenStoppingContext = true;
 
-    /**
-     * Should Tomcat attempt to clear references to classes loaded by the web 
application class loader from the
-     * ObjectStreamClass caches?
-     */
-    private boolean clearReferencesObjectStreamClassCaches = true;
-
     /**
      * Should Tomcat attempt to clear references to classes loaded by this 
class loader from ThreadLocals?
      */
@@ -2648,19 +2642,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
     }
 
 
-    public boolean getClearReferencesObjectStreamClassCaches() {
-        return clearReferencesObjectStreamClassCaches;
-    }
-
-
-    public void setClearReferencesObjectStreamClassCaches(boolean 
clearReferencesObjectStreamClassCaches) {
-        boolean oldClearReferencesObjectStreamClassCaches = 
this.clearReferencesObjectStreamClassCaches;
-        this.clearReferencesObjectStreamClassCaches = 
clearReferencesObjectStreamClassCaches;
-        support.firePropertyChange("clearReferencesObjectStreamClassCaches", 
oldClearReferencesObjectStreamClassCaches,
-                this.clearReferencesObjectStreamClassCaches);
-    }
-
-
     public boolean getClearReferencesThreadLocals() {
         return clearReferencesThreadLocals;
     }
@@ -4745,7 +4726,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
                     
cl.setClearReferencesStopThreads(getClearReferencesStopThreads());
                     
cl.setClearReferencesStopTimerThreads(getClearReferencesStopTimerThreads());
                     
cl.setClearReferencesHttpClientKeepAliveThread(getClearReferencesHttpClientKeepAliveThread());
-                    
cl.setClearReferencesObjectStreamClassCaches(getClearReferencesObjectStreamClassCaches());
                     
cl.setClearReferencesThreadLocals(getClearReferencesThreadLocals());
                     
cl.setSkipMemoryLeakChecksOnJvmShutdown(getSkipMemoryLeakChecksOnJvmShutdown());
                 }
diff --git a/java/org/apache/catalina/loader/WebappClassLoaderBase.java 
b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
index b637fdd323..fede505739 100644
--- a/java/org/apache/catalina/loader/WebappClassLoaderBase.java
+++ b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
@@ -352,12 +352,6 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
      */
     private boolean clearReferencesHttpClientKeepAliveThread = true;
 
-    /**
-     * Should Tomcat attempt to clear references to classes loaded by this 
class
-     * loader from the ObjectStreamClass caches?
-     */
-    private boolean clearReferencesObjectStreamClassCaches = true;
-
     /**
      * Should Tomcat attempt to clear references to classes loaded by this 
class
      * loader from ThreadLocals?
@@ -539,17 +533,6 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
     }
 
 
-    public boolean getClearReferencesObjectStreamClassCaches() {
-        return clearReferencesObjectStreamClassCaches;
-    }
-
-
-    public void setClearReferencesObjectStreamClassCaches(
-            boolean clearReferencesObjectStreamClassCaches) {
-        this.clearReferencesObjectStreamClassCaches = 
clearReferencesObjectStreamClassCaches;
-    }
-
-
     public boolean getClearReferencesThreadLocals() {
         return clearReferencesThreadLocals;
     }
@@ -1518,11 +1501,6 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
         // Stop any threads the web application started
         clearReferencesThreads();
 
-        // Clear any references retained in the serialization caches
-        if (clearReferencesObjectStreamClassCaches && 
!JreCompat.isGraalAvailable()) {
-            clearReferencesObjectStreamClassCaches();
-        }
-
         // Check for leaks triggered by ThreadLocals loaded by this class 
loader
         if (clearReferencesThreadLocals && !JreCompat.isGraalAvailable()) {
             checkThreadLocalsForLeaks();
@@ -1669,7 +1647,7 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
                     // shutting down the executor
                     boolean usingExecutor = false;
                     try {
-                        Object executor = 
JreCompat.getInstance().getExecutor(thread);
+                        Object executor = getExecutor(thread);
                         if (executor instanceof ThreadPoolExecutor) {
                             ((ThreadPoolExecutor) executor).shutdownNow();
                             usingExecutor = true;
@@ -1726,6 +1704,70 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
     }
 
 
+    private Object getExecutor(Thread thread)
+            throws NoSuchFieldException, SecurityException, 
IllegalArgumentException, IllegalAccessException {
+
+        Object result = null;
+
+        // Runnable wrapped by Thread
+        // "target" in Sun/Oracle JDK
+        // "runnable" in IBM JDK
+        // "action" in Apache Harmony
+        Object target = null;
+        for (String fieldName : new String[] { "target", "runnable", "action" 
}) {
+            try {
+                Field targetField = 
thread.getClass().getDeclaredField(fieldName);
+                targetField.setAccessible(true);
+                target = targetField.get(thread);
+                break;
+            } catch (NoSuchFieldException nfe) {
+                continue;
+            }
+        }
+
+        // "java.util.concurrent" code is in public domain,
+        // so all implementations are similar including our
+        // internal fork.
+        if (target != null && target.getClass().getCanonicalName() != null &&
+                (target.getClass().getCanonicalName().equals(
+                        
"org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") ||
+                        target.getClass().getCanonicalName().equals(
+                                
"java.util.concurrent.ThreadPoolExecutor.Worker"))) {
+            Field executorField = target.getClass().getDeclaredField("this$0");
+            executorField.setAccessible(true);
+            result = executorField.get(target);
+        }
+
+        if (result == null) {
+            Object holder = null;
+            Object task = null;
+            try {
+                Field holderField = 
thread.getClass().getDeclaredField("holder");
+                holderField.setAccessible(true);
+                holder = holderField.get(thread);
+
+                Field taskField = holder.getClass().getDeclaredField("task");
+                taskField.setAccessible(true);
+                task = taskField.get(holder);
+            } catch (NoSuchFieldException nfe) {
+                return null;
+            }
+
+            if (task!= null && task.getClass().getCanonicalName() != null &&
+                    (task.getClass().getCanonicalName().equals(
+                            
"org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") ||
+                            task.getClass().getCanonicalName().equals(
+                                    
"java.util.concurrent.ThreadPoolExecutor.Worker"))) {
+                Field executorField = 
task.getClass().getDeclaredField("this$0");
+                executorField.setAccessible(true);
+                result = executorField.get(task);
+            }
+        }
+
+        return result;
+    }
+
+
     /*
      * Look at a threads stack trace to see if it is a request thread or not. 
It
      * isn't perfect, but it should be good-enough for most cases.
@@ -2110,27 +2152,6 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
     }
 
 
-    private void clearReferencesObjectStreamClassCaches() {
-        if (JreCompat.isJre19Available()) {
-            // The memory leak this fixes has been fixed in Java 19 onwards,
-            // 17.0.4 onwards and 11.0.16 onwards
-            // See https://bugs.openjdk.java.net/browse/JDK-8277072
-            return;
-        }
-        try {
-            Class<?> clazz = Class.forName("java.io.ObjectStreamClass$Caches");
-            clearCache(clazz, "localDescs");
-            clearCache(clazz, "reflectors");
-        } catch (ReflectiveOperationException | SecurityException | 
ClassCastException e) {
-            log.warn(sm.getString(
-                    "webappClassLoader.clearObjectStreamClassCachesFail", 
getContextName()), e);
-        } catch (InaccessibleObjectException e) {
-            // Must be running on without the necessary command line options.
-            log.warn(sm.getString("webappClassLoader.addExportsJavaIo", 
getCurrentModuleName()));
-        }
-    }
-
-
     private String getCurrentModuleName() {
         String moduleName = this.getClass().getModule().getName();
         if (moduleName == null) {
@@ -2140,29 +2161,6 @@ public abstract class WebappClassLoaderBase extends 
URLClassLoader
     }
 
 
-    private void clearCache(Class<?> target, String mapName)
-            throws ReflectiveOperationException, SecurityException, 
ClassCastException {
-        Field f = target.getDeclaredField(mapName);
-        f.setAccessible(true);
-        Object map = f.get(null);
-        // Avoid trying to clear references if Tomcat is running on a JRE that
-        // includes the fix for this memory leak
-        // See https://bugs.openjdk.java.net/browse/JDK-8277072
-        if (map instanceof Map<?,?>) {
-            Iterator<?> keys = ((Map<?,?>) map).keySet().iterator();
-            while (keys.hasNext()) {
-                Object key = keys.next();
-                if (key instanceof Reference) {
-                    Object clazz = ((Reference<?>) key).get();
-                    if (loadedByThisOrChild(clazz)) {
-                        keys.remove();
-                    }
-                }
-            }
-        }
-    }
-
-
     /**
      * Find specified class in local repositories.
      *
diff --git a/java/org/apache/tomcat/util/compat/Jre19Compat.java 
b/java/org/apache/tomcat/util/compat/Jre19Compat.java
deleted file mode 100644
index 60ee0c2dc1..0000000000
--- a/java/org/apache/tomcat/util/compat/Jre19Compat.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.tomcat.util.compat;
-
-import java.lang.reflect.Field;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.res.StringManager;
-
-public class Jre19Compat extends JreCompat {
-
-    private static final Log log = LogFactory.getLog(Jre19Compat.class);
-    private static final StringManager sm = 
StringManager.getManager(Jre19Compat.class);
-
-    private static final boolean supported;
-
-    static {
-        // Don't need any Java 19 specific classes (yet) so just test for one 
of
-        // the new ones for now.
-        Class<?> c1 = null;
-        try {
-            c1 = Class.forName("java.lang.WrongThreadException");
-        } catch (ClassNotFoundException cnfe) {
-            // Must be pre-Java 19
-            log.debug(sm.getString("jre19Compat.javaPre19"), cnfe);
-        }
-
-        supported = (c1 != null);
-    }
-
-    static boolean isSupported() {
-        return supported;
-    }
-
-    @Override
-    public Object getExecutor(Thread thread)
-            throws NoSuchFieldException, SecurityException, 
IllegalArgumentException, IllegalAccessException {
-
-        Object result = super.getExecutor(thread);
-
-        if (result == null) {
-            Object holder = null;
-            Object task = null;
-            try {
-                Field holderField = 
thread.getClass().getDeclaredField("holder");
-                holderField.setAccessible(true);
-                holder = holderField.get(thread);
-
-                Field taskField = holder.getClass().getDeclaredField("task");
-                taskField.setAccessible(true);
-                task = taskField.get(holder);
-            } catch (NoSuchFieldException nfe) {
-                return null;
-            }
-
-            if (task!= null && task.getClass().getCanonicalName() != null &&
-                    (task.getClass().getCanonicalName().equals(
-                            
"org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") ||
-                            task.getClass().getCanonicalName().equals(
-                                    
"java.util.concurrent.ThreadPoolExecutor.Worker"))) {
-                Field executorField = 
task.getClass().getDeclaredField("this$0");
-                executorField.setAccessible(true);
-                result = executorField.get(task);
-            }
-        }
-
-        return result;
-    }
-}
diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java 
b/java/org/apache/tomcat/util/compat/JreCompat.java
index 3de6908893..334115acc3 100644
--- a/java/org/apache/tomcat/util/compat/JreCompat.java
+++ b/java/org/apache/tomcat/util/compat/JreCompat.java
@@ -16,18 +16,15 @@
  */
 package org.apache.tomcat.util.compat;
 
-import java.lang.reflect.Field;
-
 /**
  * This is the base implementation class for JRE compatibility and provides an
- * implementation based on Java 17. Sub-classes may extend this class and 
provide
+ * implementation based on Java 21. Sub-classes may extend this class and 
provide
  * alternative implementations for later JRE versions
  */
 public class JreCompat {
 
     private static final JreCompat instance;
     private static final boolean graalAvailable;
-    private static final boolean jre19Available;
 
     static {
         boolean result = false;
@@ -41,15 +38,8 @@ public class JreCompat {
         }
         graalAvailable = result || 
System.getProperty("org.graalvm.nativeimage.imagecode") != null;
 
-        // This is Tomcat 11.0.x with a minimum Java version of Java 17.
-        // Look for the highest supported JVM first
-        if (Jre19Compat.isSupported()) {
-            instance = new Jre19Compat();
-            jre19Available = true;
-        } else {
-            instance = new JreCompat();
-            jre19Available = false;
-        }
+        // This is Tomcat 11.0.x with a minimum Java version of Java 21.
+        instance = new JreCompat();
     }
 
 
@@ -61,68 +51,4 @@ public class JreCompat {
     public static boolean isGraalAvailable() {
         return graalAvailable;
     }
-
-
-    public static boolean isJre19Available() {
-        return jre19Available;
-    }
-
-
-    // Java 17 implementations of Java 19 methods
-
-    /**
-     * Obtains the executor, if any, used to create the provided thread.
-     *
-     * @param thread    The thread to examine
-     *
-     * @return  The executor, if any, that created the provided thread
-     *
-     * @throws NoSuchFieldException
-     *              If a field used via reflection to obtain the executor 
cannot
-     *              be found
-     * @throws SecurityException
-     *              If a security exception occurs while trying to identify the
-     *              executor
-     * @throws IllegalArgumentException
-     *              If the instance object does not match the class of the 
field
-     *              when obtaining a field value via reflection
-     * @throws IllegalAccessException
-     *              If a field is not accessible due to access restrictions
-     */
-    public Object getExecutor(Thread thread)
-            throws NoSuchFieldException, SecurityException, 
IllegalArgumentException, IllegalAccessException {
-
-        Object result = null;
-
-        // Runnable wrapped by Thread
-        // "target" in Sun/Oracle JDK
-        // "runnable" in IBM JDK
-        // "action" in Apache Harmony
-        Object target = null;
-        for (String fieldName : new String[] { "target", "runnable", "action" 
}) {
-            try {
-                Field targetField = 
thread.getClass().getDeclaredField(fieldName);
-                targetField.setAccessible(true);
-                target = targetField.get(thread);
-                break;
-            } catch (NoSuchFieldException nfe) {
-                continue;
-            }
-        }
-
-        // "java.util.concurrent" code is in public domain,
-        // so all implementations are similar including our
-        // internal fork.
-        if (target != null && target.getClass().getCanonicalName() != null &&
-                (target.getClass().getCanonicalName().equals(
-                        
"org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") ||
-                        target.getClass().getCanonicalName().equals(
-                                
"java.util.concurrent.ThreadPoolExecutor.Worker"))) {
-            Field executorField = target.getClass().getDeclaredField("this$0");
-            executorField.setAccessible(true);
-            result = executorField.get(target);
-        }
-
-        return result;
-    }
 }
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings.properties
deleted file mode 100644
index a3d30954e7..0000000000
--- a/java/org/apache/tomcat/util/compat/LocalStrings.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-jre19Compat.javaPre19=Class not found so assuming code is running on a 
pre-Java 19 JVM
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties
deleted file mode 100644
index ee07dd61d3..0000000000
--- a/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-jre19Compat.javaPre19=Classe non trouvée donc le code est exécutée sur une JVM 
antérieure à Java 19
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties
deleted file mode 100644
index 2246b19e0e..0000000000
--- a/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-jre19Compat.javaPre19=クラスが見つからないため、Java 19より前のJVMでコードが実行されていると仮定します
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_ko.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings_ko.properties
deleted file mode 100644
index 42a25ed603..0000000000
--- a/java/org/apache/tomcat/util/compat/LocalStrings_ko.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-jre19Compat.javaPre19=클래스가 발견되지 않으므로, 코드가 자바 19 이전 버전의 JVM에서 실행 중이라고 가정합니다.
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_zh_CN.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings_zh_CN.properties
deleted file mode 100644
index 571a2bffd2..0000000000
--- a/java/org/apache/tomcat/util/compat/LocalStrings_zh_CN.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-jre19Compat.javaPre19=该类未找到,因此推测当前代码运行在Java 19版本之前的虚拟机上
diff --git a/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java 
b/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
index d34cafa0db..8dea5e7f84 100644
--- a/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
+++ b/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
@@ -42,7 +42,6 @@ import org.apache.catalina.startup.Tomcat;
 import org.apache.coyote.http2.Http2TestBase;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
-import org.apache.tomcat.util.compat.JreCompat;
 
 /*
  * Split into multiple tests as a single test takes so long it impacts the time
@@ -244,13 +243,12 @@ public class HttpServletDoHeadBaseTest extends 
Http2TestBase {
             boolean resetBufferSize = false;
 
             if 
(Boolean.parseBoolean(getServletConfig().getInitParameter(LEGACY_DO_HEAD)) &&
-                    JreCompat.isJre19Available() && 
"HEAD".equals(req.getMethod()) && useWriter &&
-                    resetType != ResetType.NONE) {
+                    "HEAD".equals(req.getMethod()) && useWriter && resetType 
!= ResetType.NONE) {
                 /*
-                 * Using legacy HEAD handling with a Writer on Java 19+.
+                 * Using legacy HEAD handling with a Writer.
+                 *
                  * HttpServlet wraps the response. The test is sensitive to
-                 * buffer sizes. The size of the buffer HttpServlet uses varies
-                 * with Java version. For the tests to pass the number of
+                 * buffer sizes. For the tests to pass the number of
                  * characters that can be written before the response is
                  * committed needs to be the same.
                  *
@@ -258,14 +256,8 @@ public class HttpServletDoHeadBaseTest extends 
Http2TestBase {
                  * bytes. When a Writer is used, an additional 8192 byte buffer
                  * is used for char->byte.
                  *
-                 * With Java <19, the char->byte buffer used by HttpServlet
-                 * processing HEAD requests in legacy mode is created as a 8192
-                 * byte buffer which is consistent with the buffer Tomcat uses
-                 * internally.
-                 *
-                 * With Java 19+, the char->byte buffer used by HttpServlet
-                 * processing HEAD requests in legacy mode is created as a 512
-                 * byte buffer.
+                 * The char->byte buffer used by HttpServlet processing HEAD
+                 * requests in legacy mode is created as a 512 byte buffer.
                  *
                  * If the response isn't reset, none of this matters as it is
                  * just the size of the response buffer and the size of the
@@ -273,13 +265,12 @@ public class HttpServletDoHeadBaseTest extends 
Http2TestBase {
                  * However, if the response is reset then things get 
interesting
                  * as the amount of response data that can be written before
                  * committing the response is the combination of the char->byte
-                 * buffer and the response buffer. Because the char->byte 
buffer
-                 * size in legacy mode varies with Java version, the size of 
the
-                 * response buffer needs to be adjusted to compensate so that
-                 * both GET and HEAD can write the same amount of data before
-                 * committing the response. To make matters worse, to obtain 
the
-                 * correct behaviour the response buffer size needs to be reset
-                 * back to 8192 after the reset.
+                 * buffer and the response buffer. The size of the response
+                 * buffer needs to be adjusted so that both GET and HEAD can
+                 * write the same amount of data before committing the 
response.
+                 * To make matters worse, to obtain the correct behaviour the
+                 * response buffer size needs to be reset back to 8192 after 
the
+                 * reset.
                  *
                  * This is why the legacy mode is problematic and the new
                  * approach of the container handling HEAD is better.
@@ -290,9 +281,7 @@ public class HttpServletDoHeadBaseTest extends 
Http2TestBase {
                     adjustedBufferSize = originalBufferSize;
                 }
 
-                // Adjust for smaller initial char -> byte buffer in Java 19+
-                // originalBufferSize initial size in Java <19
-                // 512 initial size in Java 19+
+                // Adjust for smaller initial char -> byte buffer
                 adjustedBufferSize = adjustedBufferSize + originalBufferSize - 
512;
 
                 resetBufferSize = true;
diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml
index e5aa73f86d..0f3798bfde 100644
--- a/webapps/docs/config/context.xml
+++ b/webapps/docs/config/context.xml
@@ -789,21 +789,6 @@
         not specified, the default value of <code>true</code> will be used.</p>
       </attribute>
 
-      <attribute name="clearReferencesObjectStreamClassCaches" 
required="false">
-        <p>If <code>true</code>, when the web application is stopped Tomcat
-        looks for <code>SoftReference</code>s to classes loaded by the web
-        application in the <code>ObjectStreamClass</code> class used for
-        serialization and clears any <code>SoftReference</code>s it finds. This
-        feature uses reflection to identify the <code>SoftReference</code>s and
-        therefore requires that the command line option
-        <code>-XaddExports:java.base/java.io=ALL-UNNAMED</code> is set. If not
-        specified, the default value of <code>true</code> will be used.</p>
-        <p>The memory leak associated with <code>ObjectStreamClass</code> has
-        been fixed in Java 19 onwards, Java 17.0.4 onwards and Java 11.0.16
-        onwards. The check will be disabled when running on a version
-        of Java that contains the fix.</p>
-      </attribute>
-
       <attribute name="clearReferencesRmiTargets" required="false">
         <p>If <code>true</code>, Tomcat looks for memory leaks associated with
         RMI Targets and clears any it finds. This feature uses reflection to


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to