dependabot[bot] opened a new pull request, #25955: URL: https://github.com/apache/camel/pull/25955
Bumps [io.github.classgraph:classgraph](https://github.com/classgraph/classgraph) from 4.8.193 to 4.8.194. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/classgraph/classgraph/releases">io.github.classgraph:classgraph's releases</a>.</em></p> <blockquote> <h2>ClassGraph 4.8.194</h2> <p><strong>ClassGraph 5.0.0 is coming shortly</strong>, and requires JDK 17 or newer. 4.8.194 is a bugfix release on the 4.x maintenance branch, and continues the file-by-file audit of the codebase that produced 4.8.190 through 4.8.193. As before, most of the bugs listed here were found by Claude through careful code analysis, and were fixed on the v5 branch and backported to v4.</p> <p>The theme this time is the order in which scan sources are searched: which classloader's copy of a class wins, where the application classpath sits in that order, and how module layers are traversed. There is also a fix for a scan that never returns.</p> <h2>Bug fixes: deadlock</h2> <ul> <li><strong>A scan started from a thread holding a classloader lock never returned</strong> (<a href="https://redirect.github.com/classgraph/classgraph/issues/933">#933</a>). <code>scan()</code> and <code>scan(int)</code> submitted the <code>Scanner</code> to an <code>ExecutorService</code> and blocked the calling thread on the <code>Future</code>, so the first classes the scan needed were loaded on a worker thread. If the calling thread held a lock that the classloader also acquires — not unusual during a host's startup, as in Fabric/Knot — the worker blocked in <code>ClassLoader.loadClass</code> while the caller waited for it, and neither ever moved. Neither side of that cycle is a monitor that both threads contend for, so the JVM did not report it as a deadlock either, and <code>jstack</code> showed nothing wrong. The <code>Scanner</code> now runs on the calling thread; the <code>ExecutorService</code> is still used for the parallel stages of the scan, and is not used at al l when <code>numParallelTasks</code> is 1, so <code>scan(1)</code> now loads every class it needs on the calling thread and cannot deadlock that way. <code>scanAsync()</code> is unchanged, since running on a pool thread is its purpose.</li> </ul> <h2>Bug fixes: classpath and classloader order</h2> <ul> <li> <p><strong>A classloader could be ordered behind its own ancestors.</strong> The list of classloaders found in the environment was seeded with the thread context classloader, ClassGraph's own classloader and the system classloader before the call stack was read, so an ancestor could be placed ahead of the descendant that actually called ClassGraph. Only the position of the first classloader of a delegation chain to be reached is decided by that list — once a classloader is reached, its <code>ClassLoaderHandler</code> decides where its ancestors' classpath elements go relative to its own — so pinning an ancestor first silently converted parent-last delegation, the default for Tomcat's <code>WebappClassLoader</code> and for Spring Boot DevTools' <code>RestartClassLoader</code>, into parent-first delegation, inverting the class masking order. The classloaders found in the environment are now sorted by descending delegation depth, which cannot place an ancestor ahead of one of its descendants, and the call stack is read innermost frame first, so the immediate caller's classloader is preferred over that of the code that called it, mirroring how <code>Class.forName(String)</code> resolves against its immediate caller. Classloaders added with <code>addClassLoader()</code> are still appended after them, as that method documents.</p> </li> <li> <p><strong>The application classpath was searched after the classloaders that delegate to it.</strong> The <code>java.class.path</code> entries were appended after every classloader had been visited, which inverts the masking order: a class present both on the application classpath and in a child classloader was reported from the child, whereas parent-first delegation makes the JVM load the application classloader's copy. Those entries are now contributed by the handler for the application classloader, so they land at the position the application classloader takes in the delegation order, like any other classloader's entries. This also makes <code>ignoreParentClassLoaders()</code> behave as its documentation says: it now leaves out only the entries that a parent classloader declares, instead of also dropping the application classloader's own entries when the application classloader is itself one of the classloaders being searched.</p> </li> <li> <p><strong>A module layer reachable from more than one named layer was listed more than once</strong>, and the resulting order then depended on which layers the caller happened to name rather than on the layer DAG alone. Naming a parent layer and its child, in either order, gave the same result — the child first — so asking for the parent's modules to be searched first had no effect. The visited set is now shared across all top-level layers, so a layer named directly keeps the position its own name gives it, and is reached indirectly through <code>ModuleLayer#parents()</code> only if the caller did not name it. The javadoc now also states why a layer's own modules come before its parent layers': the classloader a layer creates is a <code>jdk.internal.loader.Loader</code>, whose <code>loadClass</code> checks this layer's own modules before the parent layers' and before its parent classloader — the reverse of the classloader axis, and observable, since a child layer may define a module with the same name as one in a parent layer and the child's copy then wins.</p> </li> <li> <p><strong>Six <code>ClassLoaderHandler</code>s were missing classpath entries that their classloaders expose.</strong> An audit of the source of every supported classloader turned these up; nothing that was already read has been removed, since a field or method absent from the current source may still be present in an older version. Uno-JAR also accepts extra entries in the <code>uno-jar.class.path</code> system property, separated by <code>|</code>. A JBoss <code>ResourceLoader</code> that wraps another one, such as a <code>FilteredResourceLoader</code>, exposes only the location of the loader it delegates to. An Equinox <code>BundleFileWrapper</code> installed by a framework extension copies only the base file of the bundle file it wraps, so without following its <code>bundleFile</code> field the sub-path within the bundle is lost. A Felix <code>Content</code> with no file of its own delegates to the <code>Content</code> in its <code>m_content</code> field. The bundle file of a n older Equinox classpath entry can be a nested directory or a wrapper chain, exactly as in newer versions, and the bundle's fragments have classpath entries of their own. A WebSphere Liberty <code>AppClassLoader</code> delegates to the classloaders of its configured libraries, split by precedence into <code>beforeAppDelegateLoaders</code> and <code>afterAppDelegateLoaders</code>, and a <code>ThreadContextClassLoader</code> searches the classloaders in <code>followOnClassLoaders</code> after its parent.</p> </li> </ul> <h2>Bug fixes: resource paths</h2> <ul> <li><strong>A package root within a jarfile was separated from a resource path with <code>!/</code> rather than <code>/</code>.</strong> A classpath entry can name a package root within a jarfile, e.g. <code>app.jar!/BOOT-INF</code>, and <code>Resource#getURI()</code> appended <code>!/</code> between the URI of the classpath element and the path of the resource within it, giving <code>app.jar!/BOOT-INF!/classes/hello/HelloController.class</code> — a URL with two <code>!/</code> separators but only one archive in it, which does not resolve. A package root is a directory within the jarfile, not a jarfile nested inside it, so a resource beneath it is separated from it by <code>/</code>. The default automatic package root prefixes masked this for the paths they cover.</li> </ul> <h2>Bug fixes: classfile parsing</h2> <ul> <li> <p><strong>A class using the JVMS-specified encoding of a <code>Class</code>-valued annotation element vanished from scan results.</strong> JVMS 4.7.16.1 specifies that the <code>class_info_index</code> of a tag <code>c</code> annotation element value refers to a <code>CONSTANT_Class</code> entry, but javac writes the type descriptor directly as a <code>CONSTANT_Utf8</code> entry instead, which is what <code>AnnotationClassRef</code> expects. With a classfile that follows the spec to the letter, the binary class name failed to parse as a descriptor and the whole class was silently dropped. <code>CONSTANT_Class</code> references are now converted to type descriptors, and UTF8 constants are passed through unchanged.</p> </li> <li> <p><strong>Mixing <code>RUNTIME</code>- and <code>CLASS</code>-retention type-use annotations on one declaration dropped all the <code>RUNTIME</code> ones.</strong> javac emits both the <code>RuntimeVisibleTypeAnnotations</code> and <code>RuntimeInvisibleTypeAnnotations</code> attributes on the same target in that case, and the field, method and class attribute readers each overwrote the decorators of the first attribute with those of the second. The two lists are now merged.</p> </li> <li> <p><strong>A constant declared by an implemented interface could not be found through an implementing class.</strong> The reflection driver's member cache walked the superclass chain caching declared methods and fields, then walked the interface graph caching only declared methods. Both kinds are now cached at both traversal sites, and methods and fields are read in separate <code>try</code> blocks, so a class whose fields cannot be read still has its methods cached, and vice versa.</p> </li> </ul> <h2>Behaviour changes</h2> <ul> <li> <p><strong><code>ClassInfo#toString()</code> now names only the class in an <code>extends</code> or <code>implements</code> clause</strong>, as Java source does. It previously rendered a superclass or superinterface with its own modifiers, class type keyword and <code>extends</code>/<code>implements</code> clauses, producing output that is not a Java declaration:</p> <pre><code>public static class Child extends public abstract static Parent extends java.lang.Exception implements public abstract static Marker implements public abstract static Tag </code></pre> <p>The named class's modifiers, class type, type parameters, record parameters and supertypes all belong to its own declaration. This changes <code>toString()</code> output for any class whose supertypes have supertypes or modifiers of their own.</p> </li> </ul> <h2>Dependencies and documentation</h2> <ul> <li> <p><strong>Narcissus updated to 1.0.13</strong>, which adds a native library for Linux on arm64, so ClassGraph can read the classpath through Narcissus on that platform too.</p> </li> <li> <p>The README and the <code>CIRCUMVENT_ENCAPSULATION</code> javadoc listed the wrong set of platforms Narcissus supports: there have been no 32-bit x86 builds for a long time, and Linux arm64 and macOS arm64 were missing.</p> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/classgraph/classgraph/commit/4ac0a76370d43de4f716c6484a3c457504536405"><code>4ac0a76</code></a> [maven-release-plugin] prepare release classgraph-4.8.194</li> <li><a href="https://github.com/classgraph/classgraph/commit/3b37a812fb13b2a99524c5226d4160c32cdf9cad"><code>3b37a81</code></a> Run a blocking scan on the calling thread</li> <li><a href="https://github.com/classgraph/classgraph/commit/ff10ce496b9d34f24b713f0d1baf83bcb09fb01b"><code>ff10ce4</code></a> Name only the class in an extends or implements clause</li> <li><a href="https://github.com/classgraph/classgraph/commit/fbe71275ae4fd17ffee576168b08dce80babcba4"><code>fbe7127</code></a> Put the application classloader's classpath entries in their proper place</li> <li><a href="https://github.com/classgraph/classgraph/commit/4e090c985f7a740d7c6d5b09e6b2a0ff0df57949"><code>4e090c9</code></a> Order a classloader ahead of its own ancestors when finding scan sources</li> <li><a href="https://github.com/classgraph/classgraph/commit/ade5186f25f91e25024f621e492eead4bcf54f50"><code>ade5186</code></a> List each module layer once, in the order its own loader searches</li> <li><a href="https://github.com/classgraph/classgraph/commit/68fceaad192ff8a181d6efbb1bb3dd9fe809f13f"><code>68fceaa</code></a> Separate a package root from a resource path with '/', not '!/'</li> <li><a href="https://github.com/classgraph/classgraph/commit/b07d80f3eec27acd63afbfed2a6092c854ecad9e"><code>b07d80f</code></a> Read the classpath entries that six ClassLoaderHandlers were missing</li> <li><a href="https://github.com/classgraph/classgraph/commit/89bdb8a3f7b13a8f7e516b15f757f3daa77f42dc"><code>89bdb8a</code></a> Handle the JVMS-specified encoding of 'c' annotation element values</li> <li><a href="https://github.com/classgraph/classgraph/commit/1c2eee6e6d6eae93f0c572115b11468ac26281b8"><code>1c2eee6</code></a> Merge runtime visible and invisible type annotation attributes</li> <li>Additional commits viewable in <a href="https://github.com/classgraph/classgraph/compare/classgraph-4.8.193...classgraph-4.8.194">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
