ClassLoaderHandler for Quarkus RuntimeClassLoader 1.13.3
See original GitHub issueHey,
I run in a problem after a quarkus update to 1.13.3. I don’t know since which version the Classloader at Runtime (fast-jar) changed, but it changed to “io.quarkus.bootstrap.runner.RunnerClassLoader”.
I tried a little bit by myself and following code worked for me. Perhaps you want to use it, otherwise feel free to close this issue.
BR Tobias
/**
* Extract classpath entries from the Quarkus ClassLoader.
*/
class QuarkusClassLoaderHandler implements ClassLoaderHandler {
// Classloader until Quarkus 1.2
private static final String RUNTIME_CLASSLOADER = "io.quarkus.runner.RuntimeClassLoader";
// Classloader since Quarkus 1.3
private static final String QUARKUS_CLASSLOADER = "io.quarkus.bootstrap.classloading.QuarkusClassLoader";
// Classloader since Quarkus 1.13
private static final String QUARKUS_RUNTIME_CLASSLOADER = "io.quarkus.bootstrap.runner.RunnerClassLoader";
/**
* Class cannot be constructed.
*/
private QuarkusClassLoaderHandler() {
}
/**
* Can handle.
*
* @param classLoaderClass the classloader class
* @param log the log
* @return true, if classLoaderClass is the Quarkus RuntimeClassloader or QuarkusClassloader
*/
public static boolean canHandle(final Class<?> classLoaderClass, final LogNode log) {
return RUNTIME_CLASSLOADER.equals(classLoaderClass.getName())
|| QUARKUS_CLASSLOADER.equals(classLoaderClass.getName())
|| QUARKUS_RUNTIME_CLASSLOADER.equals(classLoaderClass.getName());
}
/**
* Find classloader order.
*
* @param classLoader the class loader
* @param classLoaderOrder the classloader order
* @param log the log
*/
public static void findClassLoaderOrder(final ClassLoader classLoader, final ClassLoaderOrder classLoaderOrder,
final LogNode log) {
classLoaderOrder.delegateTo(classLoader.getParent(), /* isParent = */ true, log);
classLoaderOrder.add(classLoader, log);
}
/**
* Find the classpath entries for the associated {@link ClassLoader}.
*
* @param classLoader the {@link ClassLoader} to find the classpath entries order for.
* @param classpathOrder a {@link ClasspathOrder} object to update.
* @param scanSpec the {@link ScanSpec}.
* @param log the log.
*/
public static void findClasspathOrder(final ClassLoader classLoader, final ClasspathOrder classpathOrder,
final ScanSpec scanSpec, final LogNode log) {
final String classLoaderName = classLoader.getClass().getName();
if (RUNTIME_CLASSLOADER.equals(classLoaderName)) {
findClasspathOrderForRuntimeClassloader(classLoader, classpathOrder, scanSpec, log);
} else if (QUARKUS_CLASSLOADER.equals(classLoaderName)) {
findClasspathOrderForQuarkusClassloader(classLoader, classpathOrder, scanSpec, log);
} else if (QUARKUS_RUNTIME_CLASSLOADER.equals(classLoaderName)) {
findClasspathOrderForQuarkusRuntimeClassloader(classLoader, classpathOrder, scanSpec, log);
}
}
@SuppressWarnings("unchecked")
private static void findClasspathOrderForQuarkusClassloader(final ClassLoader classLoader,
final ClasspathOrder classpathOrder, final ScanSpec scanSpec, final LogNode log) {
for (final Object element : (Collection<Object>) ReflectionUtils.getFieldVal(classLoader, "elements", false)) {
final String elementClassName = element.getClass().getName();
if ("io.quarkus.bootstrap.classloading.JarClassPathElement".equals(elementClassName)) {
classpathOrder.addClasspathEntry(ReflectionUtils.getFieldVal(element, "file", false), classLoader,
scanSpec, log);
} else if ("io.quarkus.bootstrap.classloading.DirectoryClassPathElement".equals(elementClassName)) {
classpathOrder.addClasspathEntry(ReflectionUtils.getFieldVal(element, "root", false), classLoader,
scanSpec, log);
}
}
}
@SuppressWarnings("unchecked")
private static void findClasspathOrderForRuntimeClassloader(final ClassLoader classLoader,
final ClasspathOrder classpathOrder, final ScanSpec scanSpec, final LogNode log) {
final Collection<Path> applicationClassDirectories = (Collection<Path>) ReflectionUtils.getFieldVal(classLoader,
"applicationClassDirectories", false);
if (applicationClassDirectories != null) {
for (final Path path : applicationClassDirectories) {
classpathOrder.addClasspathEntryObject(path.toUri(), classLoader, scanSpec, log);
}
}
}
@SuppressWarnings("unchecked")
private static void findClasspathOrderForQuarkusRuntimeClassloader(final ClassLoader classLoader,
final ClasspathOrder classpathOrder, final ScanSpec scanSpec, final LogNode log) {
for (final Object[] elementArray : ((Map<String, Object[]>) ReflectionUtils.getFieldVal(classLoader,
"resourceDirectoryMap", false)).values()) {
for (Object element : elementArray) {
final String elementClassName = element.getClass().getName();
if ("io.quarkus.bootstrap.runner.JarResource".equals(elementClassName)) {
classpathOrder.addClasspathEntry(ReflectionUtils.getFieldVal(element, "jarPath", false), classLoader,
scanSpec, log);
}
}
}
}
}
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:7 (4 by maintainers)
Top Results From Across the Web
Class Loading Reference - Quarkus
This ClassLoader is used to load the application classes and other hot deployable resources. Its parent is the base runtime ClassLoader, and it...
Read more >release - Quarkus
We released Quarkus 2.13.0.Final which, among a lot of smaller enhancements, comes with a cross site request forgery prevention filter and a Kafka...
Read more >Quarkus - Supersonic Subatomic Java
A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards. Now Available....
Read more >Building applications with Maven - Quarkus
Logging Quarkus application build classpath tree. Usually, dependencies of an application (which is a Maven project) could be displayed using mvn dependency: ...
Read more >Creating Your First Application - Quarkus
Learn how to create a Hello World Quarkus app. This guide covers: Bootstrapping an application. Creating a JAX-RS endpoint. Injecting beans.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Added and released in version 4.8.109. Thanks for the contribution and the pull request!
There is nothing specific needed for Quarkus when your project is in classfile form, with the classfiles either in directories or in jarfiles, as far as I know. But if you do use GraalVM to compile to native code, you have to do the scan before that compilation step, or it won’t work. (Android has the same constraint – you have to scan before compilation to Dalvik bytecodes.)