This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new ad1f59c016 Fix BZ 55470 - Add class path logging to help debug CNFE
ad1f59c016 is described below
commit ad1f59c016bce5f531ee930ed607e8b278539352
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Nov 6 10:07:15 2024 +0000
Fix BZ 55470 - Add class path logging to help debug CNFE
https://bz.apache.org/bugzilla/show_bug.cgi?id=55470
Based on a patch by Ralf Hauser
---
.../catalina/loader/WebappClassLoaderBase.java | 4 +
.../apache/tomcat/util/buf/LocalStrings.properties | 5 +
java/org/apache/tomcat/util/buf/ToStringUtil.java | 101 +++++++++++++++++++++
java/org/apache/tomcat/util/digester/Digester.java | 7 ++
webapps/docs/changelog.xml | 5 +
5 files changed, 122 insertions(+)
diff --git a/java/org/apache/catalina/loader/WebappClassLoaderBase.java
b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
index 478fea3ad0..8d3123dbab 100644
--- a/java/org/apache/catalina/loader/WebappClassLoaderBase.java
+++ b/java/org/apache/catalina/loader/WebappClassLoaderBase.java
@@ -73,6 +73,7 @@ import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.InstrumentableClassLoader;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tomcat.util.buf.ToStringUtil;
import org.apache.tomcat.util.collections.ConcurrentLruCache;
import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.res.StringManager;
@@ -1332,6 +1333,9 @@ public abstract class WebappClassLoaderBase extends
URLClassLoader
}
}
+ if (log.isDebugEnabled()) {
+ log.debug(ToStringUtil.classPathForCNFE(this));
+ }
throw new ClassNotFoundException(name);
}
diff --git a/java/org/apache/tomcat/util/buf/LocalStrings.properties
b/java/org/apache/tomcat/util/buf/LocalStrings.properties
index 62a62632a3..16d8352661 100644
--- a/java/org/apache/tomcat/util/buf/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/buf/LocalStrings.properties
@@ -38,6 +38,11 @@ messageBytes.illegalCharacter=The Unicode character [{0}] at
code point [{1}] ca
stringCache.byteTime=ByteCache generation time: {0}ms
stringCache.charTime=CharCache generation time: {0}ms
+toStringUtil.classpath.classloader=ClassLoader [{0}] loading classes from:
+toStringUtil.classpath.header=Logging class path for each class loader in
hierarchy to aid debugging of ClassNotFoundException
+toStringUtil.classpath.platform=JRE provided classes
+toStringUtil.classpath.unknown=Unknown - not an instance of URLClassLoader
+
uDecoder.eof=End of file (EOF)
uDecoder.isHexDigit=The hexadecimal encoding is invalid
uDecoder.noSlash=The encoded slash character is not allowed
diff --git a/java/org/apache/tomcat/util/buf/ToStringUtil.java
b/java/org/apache/tomcat/util/buf/ToStringUtil.java
new file mode 100644
index 0000000000..1d562d6f6d
--- /dev/null
+++ b/java/org/apache/tomcat/util/buf/ToStringUtil.java
@@ -0,0 +1,101 @@
+/*
+ * 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.buf;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Utility class used to provide String representations of objects. It is
typically used in debug logging.
+ */
+public class ToStringUtil {
+
+ private static final StringManager sm =
StringManager.getManager(ToStringUtil.class);
+
+ private static final String INDENT = " ";
+
+
+ private ToStringUtil() {
+ // Utility class. Hide default constructor.
+ }
+
+
+ /**
+ * Generate a String representation of the class path for the given class
loader and any parent class loaders to aid
+ * debugging of {@link ClassNotFoundException}.
+ *
+ * @param classLoader The class loader to analyse
+ *
+ * @return A String representation of the class path. The format is
undefined and may change in future point
+ * releases. The output includes new lines.
+ */
+ public static String classPathForCNFE(ClassLoader classLoader) {
+ // The result is expected to be fairly large
+ StringBuilder result = new StringBuilder(4096);
+ result.append(sm.getString("toStringUtil.classpath.header"));
+ result.append("\n");
+ while (classLoader != null) {
+ classPathForCNFE(classLoader, result);
+ classLoader = classLoader.getParent();
+ }
+ return result.toString();
+ }
+
+
+ private static void classPathForCNFE(ClassLoader classLoader,
StringBuilder result) {
+ result.append(INDENT);
+ result.append(sm.getString("toStringUtil.classpath.classloader",
classLoader));
+ result.append("\n");
+ if (classLoader instanceof URLClassLoader) {
+ URL[] urls = ((URLClassLoader) classLoader).getURLs();
+ for (URL url : urls) {
+ result.append(INDENT);
+ result.append(INDENT);
+ result.append(url);
+ result.append("\n");
+ }
+ } else if (classLoader == ClassLoader.getSystemClassLoader()) {
+ // From Java 9 the internal class loaders no longer extend
+ // URLCLassLoader
+ String cp = System.getProperty("java.class.path");
+ if (cp != null && cp.length() > 0) {
+ String[] paths = cp.split(File.pathSeparator);
+ for (String path : paths) {
+ result.append(INDENT);
+ result.append(INDENT);
+ result.append(path);
+ result.append("\n");
+ }
+ }
+ } else if (classLoader == ClassLoader.getPlatformClassLoader()) {
+ // From Java 9 the internal class loaders no longer extend
+ // URLCLassLoader
+ result.append(INDENT);
+ result.append(INDENT);
+ result.append(sm.getString("toStringUtil.classpath.platform"));
+ result.append("\n");
+ } else {
+ result.append(INDENT);
+ result.append(INDENT);
+ result.append(sm.getString("toStringUtil.classpath.unknown"));
+ result.append("\n");
+ }
+ }
+}
diff --git a/java/org/apache/tomcat/util/digester/Digester.java
b/java/org/apache/tomcat/util/digester/Digester.java
index e7c7a533c9..b00155c726 100644
--- a/java/org/apache/tomcat/util/digester/Digester.java
+++ b/java/org/apache/tomcat/util/digester/Digester.java
@@ -44,6 +44,7 @@ import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.IntrospectionUtils.PropertySource;
import org.apache.tomcat.util.buf.B2CConverter;
+import org.apache.tomcat.util.buf.ToStringUtil;
import org.apache.tomcat.util.res.StringManager;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
@@ -1275,6 +1276,12 @@ public class Digester extends DefaultHandler2 {
log.trace(" Fire begin() for " + rule);
}
rule.begin(namespaceURI, name, list);
+ } catch (ClassNotFoundException cnfe) {
+ log.error(sm.getString("digester.error.begin"), cnfe);
+ if (log.isDebugEnabled()) {
+
log.debug(ToStringUtil.classPathForCNFE(getClassLoader()));
+ }
+ throw createSAXException(cnfe);
} catch (Exception e) {
log.error(sm.getString("digester.error.begin"), e);
throw createSAXException(e);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index c0ee880791..c378b8d2ae 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -111,6 +111,11 @@
Add support for the new Servlet API method
<code>HttpServletResponse.sendEarlyHints()</code>. (markt)
</add>
+ <add>
+ <fix>55470</fix>: Add debug logging that reports the class path when a
+ <code>ClassNotFoundException</code> occurs in the digester or the web
+ application class loader. Based on a patch by Ralf Hauser. (markt)
+ </add>
<update>
<bug>69374</bug>: Properly separate between table header and body
in <code>DefaultServlet</code>'s listing. (michaelo)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]