From 9a312024e38c816da8400d69b85da95cf67e10a5 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 29 Apr 2024 10:50:21 +0100 Subject: [PATCH 1/3] Introduce quarkus-classloader-commons and related benchmarks infrastructure --- core/runtime/pom.xml | 2 + .../bootstrap/benchmarks/pom.xml | 91 +++++++++++++++++++ .../BenchmarkClassnameToResourceName.java | 63 +++++++++++++ independent-projects/bootstrap/bom/pom.xml | 5 + .../bootstrap/classloader-commons/pom.xml | 43 +++++++++ .../commons/classloading/ClassloadHelper.java | 21 +++++ .../classloading/ClassloadHelperTest.java | 14 +++ independent-projects/bootstrap/core/pom.xml | 4 + .../classloading/QuarkusClassLoader.java | 9 +- independent-projects/bootstrap/pom.xml | 3 + independent-projects/bootstrap/runner/pom.xml | 4 + .../bootstrap/runner/RunnerClassLoader.java | 4 +- 12 files changed, 259 insertions(+), 4 deletions(-) create mode 100644 independent-projects/bootstrap/benchmarks/pom.xml create mode 100644 independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java create mode 100644 independent-projects/bootstrap/classloader-commons/pom.xml create mode 100644 independent-projects/bootstrap/classloader-commons/src/main/java/io/quarkus/commons/classloading/ClassloadHelper.java create mode 100644 independent-projects/bootstrap/classloader-commons/src/test/java/io/quarkus/commons/classloading/ClassloadHelperTest.java diff --git a/core/runtime/pom.xml b/core/runtime/pom.xml index 42fe22a7690e7..2b5605a16a65e 100644 --- a/core/runtime/pom.xml +++ b/core/runtime/pom.xml @@ -148,6 +148,7 @@ io.quarkus:quarkus-bootstrap-runner + io.quarkus:quarkus-classloader-commons io.smallrye.common:smallrye-common-constraint io.smallrye.common:smallrye-common-cpu io.smallrye.common:smallrye-common-expression @@ -237,6 +238,7 @@ org.graalvm.sdk:native-bridge io.quarkus:quarkus-bootstrap-runner + io.quarkus:quarkus-classloader-commons io.quarkus:quarkus-development-mode-spi org.jboss.logging:jboss-logging diff --git a/independent-projects/bootstrap/benchmarks/pom.xml b/independent-projects/bootstrap/benchmarks/pom.xml new file mode 100644 index 0000000000000..f56b4cc749162 --- /dev/null +++ b/independent-projects/bootstrap/benchmarks/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + quarkus-bootstrap-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + benchmarks + Quarkus - Bootstrap - JMH Benchmarks + + + + + io.quarkus + quarkus-bootstrap-bom + ${project.version} + pom + import + + + io.quarkus + quarkus-bootstrap-bom-test + ${project.version} + pom + import + + + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + provided + + + io.quarkus + quarkus-classloader-commons + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + benchmark + + + org.openjdk.jmh.Main + + + + + + + + maven-compiler-plugin + + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + + + diff --git a/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java b/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java new file mode 100644 index 0000000000000..3879ac294bb73 --- /dev/null +++ b/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java @@ -0,0 +1,63 @@ +package io.quarkus.commons.benchmarks; + +import io.quarkus.commons.classloading.ClassloadHelper; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * We benchmark this strategy with CompilerControl.Mode.EXCLUDE as this code + * is primarily useful during bootstrap. We already know JIT will do a fantastic + * job when compiling it even if it's written in less efficient ways, so there's + * no much point in optimising such for compiled code: let's choose a strategy + * that doesn't cost excessively even before JIT kicks in. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SingleShotTime) //! +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 10, time = 20, timeUnit = TimeUnit.MILLISECONDS) //ignored in single shot mode +@Measurement(iterations = 20, time = 50, timeUnit = TimeUnit.MILLISECONDS) +@Fork(2) +public class BenchmarkClassnameToResourceName { + + @Param({ "io.quarkus.commons.benchmarks.BenchmarkClassnameToResourceName" }) + public String arg; + + @Benchmark + public String checkNewMethod() { + return ClassloadHelper.fromClassNameToResourceName(arg); + } + + @Benchmark + public String oldMethod() { + return oldMethod(arg); + } + + private static String oldMethod(String name) { + return name.replace(".", "/") + ".class"; + } + + @Benchmark + public String oldAltMethod() { + return oldAltMethod(arg); + } + + private static String oldAltMethod(String name) { + return name.replace('.', '/') + ".class"; + } + + public static void main(String[] args) throws IOException { + org.openjdk.jmh.Main.main(new String[] { "-prof", "gc", "-prof", "perfnorm" }); + } + +} diff --git a/independent-projects/bootstrap/bom/pom.xml b/independent-projects/bootstrap/bom/pom.xml index 5db6112b194ad..2143268dbc458 100644 --- a/independent-projects/bootstrap/bom/pom.xml +++ b/independent-projects/bootstrap/bom/pom.xml @@ -47,6 +47,11 @@ commons-lang3 ${commons-lang.version} + + io.quarkus + quarkus-classloader-commons + ${project.version} + io.quarkus quarkus-bootstrap-core diff --git a/independent-projects/bootstrap/classloader-commons/pom.xml b/independent-projects/bootstrap/classloader-commons/pom.xml new file mode 100644 index 0000000000000..bb04452f9b68f --- /dev/null +++ b/independent-projects/bootstrap/classloader-commons/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + quarkus-bootstrap-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-classloader-commons + Quarkus - Bootstrap - Classloader common utilities + + + + + io.quarkus + quarkus-bootstrap-bom + ${project.version} + pom + import + + + io.quarkus + quarkus-bootstrap-bom-test + ${project.version} + pom + import + + + + + + + org.junit.jupiter + junit-jupiter + test + + + + diff --git a/independent-projects/bootstrap/classloader-commons/src/main/java/io/quarkus/commons/classloading/ClassloadHelper.java b/independent-projects/bootstrap/classloader-commons/src/main/java/io/quarkus/commons/classloading/ClassloadHelper.java new file mode 100644 index 0000000000000..fcf911a83e508 --- /dev/null +++ b/independent-projects/bootstrap/classloader-commons/src/main/java/io/quarkus/commons/classloading/ClassloadHelper.java @@ -0,0 +1,21 @@ +package io.quarkus.commons.classloading; + +public final class ClassloadHelper { + + private ClassloadHelper() { + //Not meant to be instantiated + } + + /** + * Helper method to convert a classname into its typical resource name: + * replace all "." with "/" and append the ".class" postfix. + * + * @param className + * @return the name of the respective resource + */ + public static String fromClassNameToResourceName(final String className) { + //Important: avoid indy! + return className.replace('.', '/').concat(".class"); + } + +} diff --git a/independent-projects/bootstrap/classloader-commons/src/test/java/io/quarkus/commons/classloading/ClassloadHelperTest.java b/independent-projects/bootstrap/classloader-commons/src/test/java/io/quarkus/commons/classloading/ClassloadHelperTest.java new file mode 100644 index 0000000000000..89f53fd0712bf --- /dev/null +++ b/independent-projects/bootstrap/classloader-commons/src/test/java/io/quarkus/commons/classloading/ClassloadHelperTest.java @@ -0,0 +1,14 @@ +package io.quarkus.commons.classloading; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ClassloadHelperTest { + + @Test + public void testFromClassToResourceName() { + Assertions.assertEquals("java/lang/String.class", ClassloadHelper.fromClassNameToResourceName("java.lang.String")); + Assertions.assertEquals(".class", ClassloadHelper.fromClassNameToResourceName("")); + } + +} diff --git a/independent-projects/bootstrap/core/pom.xml b/independent-projects/bootstrap/core/pom.xml index fe05e4cb1f81b..1fd1e4571a880 100644 --- a/independent-projects/bootstrap/core/pom.xml +++ b/independent-projects/bootstrap/core/pom.xml @@ -33,6 +33,10 @@ + + io.quarkus + quarkus-classloader-commons + io.quarkus quarkus-bootstrap-app-model diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java index 1f1c3bf2c1cdf..d02597fe8ccb3 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java @@ -1,5 +1,7 @@ package io.quarkus.bootstrap.classloading; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.IOException; @@ -64,7 +66,8 @@ public List getAllElements(boolean onlyFromCurrentClassLoader) * @param className the name of the class. */ public static boolean isClassPresentAtRuntime(String className) { - return isResourcePresentAtRuntime(className.replace('.', '/') + ".class"); + String resourceName = fromClassNameToResourceName(className); + return isResourcePresentAtRuntime(resourceName); } /** @@ -178,7 +181,7 @@ public boolean isParentFirst(String name) { try { ClassLoaderState state = getState(); synchronized (getClassLoadingLock(name)) { - String resourceName = sanitizeName(name).replace('.', '/') + ".class"; + String resourceName = fromClassNameToResourceName(name); return parentFirst(resourceName, state); } @@ -491,7 +494,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE if (c != null) { return c; } - String resourceName = sanitizeName(name).replace('.', '/') + ".class"; + String resourceName = fromClassNameToResourceName(name); if (state.bannedResources.contains(resourceName)) { throw new ClassNotFoundException(name); } diff --git a/independent-projects/bootstrap/pom.xml b/independent-projects/bootstrap/pom.xml index c7193b0a4a094..6e310c6d24df8 100644 --- a/independent-projects/bootstrap/pom.xml +++ b/independent-projects/bootstrap/pom.xml @@ -38,6 +38,7 @@ 3.2.1 3.2.5 3.1.7 + 1.37 3.25.3 @@ -89,6 +90,8 @@ core runner gradle-resolver + classloader-commons + benchmarks diff --git a/independent-projects/bootstrap/runner/pom.xml b/independent-projects/bootstrap/runner/pom.xml index f32872fa86a74..8549283dd2c6d 100644 --- a/independent-projects/bootstrap/runner/pom.xml +++ b/independent-projects/bootstrap/runner/pom.xml @@ -38,6 +38,10 @@ + + io.quarkus + quarkus-classloader-commons + io.smallrye.common smallrye-common-io diff --git a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/RunnerClassLoader.java b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/RunnerClassLoader.java index 62c02e8fe08d3..e034638a4fd70 100644 --- a/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/RunnerClassLoader.java +++ b/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/RunnerClassLoader.java @@ -1,5 +1,7 @@ package io.quarkus.bootstrap.runner; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -97,7 +99,7 @@ public Class loadClass(String name, boolean resolve) throws ClassNotFoundExce resources = resourceDirectoryMap.get(dirName); } if (resources != null) { - String classResource = name.replace('.', '/') + ".class"; + String classResource = fromClassNameToResourceName(name); for (ClassLoadingResource resource : resources) { accessingResource(resource); byte[] data = resource.getResourceData(classResource); From df750d869424a07f4950ce821444e5ec32a85639 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Fri, 3 May 2024 10:19:32 +0100 Subject: [PATCH 2/3] Adding a note for future --- .../io/quarkus/bootstrap/classloading/QuarkusClassLoader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java index d02597fe8ccb3..bd9c962588950 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java @@ -594,6 +594,7 @@ public List getLocalClassNames() { List ret = new ArrayList<>(); for (String name : getState().loadableResources.keySet()) { if (name.endsWith(".class")) { + //TODO: clients of this method actually need the non-transformed variant and are transforming it back !? ret.add(name.substring(0, name.length() - 6).replace('/', '.')); } } From ce4471f489d67305b5904a29def3accb1a4f7fee Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Fri, 3 May 2024 10:28:59 +0100 Subject: [PATCH 3/3] Start using the new helper from more modules --- core/deployment/pom.xml | 4 ++++ .../main/java/io/quarkus/deployment/CodeGenerator.java | 4 +++- .../io/quarkus/deployment/GeneratedClassGizmoAdaptor.java | 4 +++- .../io/quarkus/deployment/dev/IsolatedDevModeMain.java | 4 +++- .../deployment/dev/filesystem/ReloadableFileManager.java | 6 ++++-- .../quarkus/deployment/dev/testing/JunitTestRunner.java | 7 +++++-- .../java/io/quarkus/deployment/index/IndexWrapper.java | 4 +++- .../quarkus/deployment/pkg/steps/JarResultBuildStep.java | 5 +++-- .../steps/AdditionalClassLoaderResourcesBuildStep.java | 4 +++- .../java/io/quarkus/deployment/steps/BannerProcessor.java | 4 +++- .../deployment/steps/ClassTransformingBuildStep.java | 8 +++++--- .../src/main/java/io/quarkus/deployment/util/IoUtil.java | 4 +++- .../io/quarkus/runner/bootstrap/StartupActionImpl.java | 4 +++- .../quarkus/deployment/pkg/steps/BannerProcessorTest.java | 3 ++- .../java/io/quarkus/deployment/util/JandexUtilTest.java | 4 +++- .../hibernate/orm/runtime/boot/scan/QuarkusScanner.java | 5 ++++- .../java/io/quarkus/qute/deployment/TypeInfosTest.java | 4 +++- .../test/java/io/quarkus/qute/deployment/TypesTest.java | 4 +++- .../server/deployment/FilterClassIntrospector.java | 5 ++++- .../deployment/MessageBodyWriterTransformerUtils.java | 5 ++++- .../server/test/simple/IllegalClassExceptionMapper.java | 4 +++- .../test/rolesallowed/ConfigExpressionDetectionTest.java | 5 ++++- .../kafka/deployment/DefaultSerdeConfigTest.java | 4 +++- .../ReflectiveClassForValueSerializerPayloadTest.java | 4 +++- .../pulsar/deployment/DefaultSchemaConfigTest.java | 4 +++- .../deployment/ConfigPropertyBuildItemCandidateUtil.java | 5 ++++- .../spring/data/deployment/MethodNameParserTest.java | 3 ++- .../arc/processor/bcextensions/ExtensionInvoker.java | 2 +- .../benchmarks/BenchmarkClassnameToResourceName.java | 7 ++++--- independent-projects/bootstrap/maven-resolver/pom.xml | 4 ++++ .../resolver/maven/options/BootstrapMavenOptions.java | 3 ++- .../main/java/io/quarkus/maven/utilities/MojoUtils.java | 3 ++- .../main/java/io/quarkus/test/common/PathTestHelper.java | 6 ++++-- .../test/component/QuarkusComponentTestExtension.java | 4 +++- .../test/junit/AbstractJvmQuarkusTestExtension.java | 3 ++- 35 files changed, 112 insertions(+), 41 deletions(-) diff --git a/core/deployment/pom.xml b/core/deployment/pom.xml index 059176771f34b..367713725caf6 100644 --- a/core/deployment/pom.xml +++ b/core/deployment/pom.xml @@ -14,6 +14,10 @@ Quarkus - Core - Deployment + + io.quarkus + quarkus-classloader-commons + org.aesh readline diff --git a/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java index 71852e90e5c86..92abc57bd3e64 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java @@ -1,5 +1,7 @@ package io.quarkus.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.BufferedWriter; import java.io.IOException; import java.io.UncheckedIOException; @@ -381,7 +383,7 @@ private static Map> getUnavailableConfigServices(ResolvedDe .map(String::trim) // skip comments and empty lines .filter(line -> !line.startsWith("#") && !line.isEmpty()) - .filter(className -> classLoader.getResource(className.replace('.', '/') + ".class") == null) + .filter(className -> classLoader.getResource(fromClassNameToResourceName(className)) == null) .forEach(unavailableList::add); } catch (IOException e) { throw new UncheckedIOException("Failed to read " + serviceFile, e); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmoAdaptor.java b/core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmoAdaptor.java index e8a15b51ed07b..eaff60bf8855a 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmoAdaptor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmoAdaptor.java @@ -1,5 +1,7 @@ package io.quarkus.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.StringWriter; import java.io.Writer; import java.util.List; @@ -77,7 +79,7 @@ public static boolean isApplicationClass(String className) { .getContextClassLoader(); //if the class file is present in this (and not the parent) CL then it is an application class List res = cl - .getElementsWithResource(className.replace('.', '/') + ".class", true); + .getElementsWithResource(fromClassNameToResourceName(className), true); return !res.isEmpty(); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java index ea2ad5dc6a8b0..0fbd24bd9f3b7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java @@ -36,6 +36,7 @@ import io.quarkus.builder.BuildChainBuilder; import io.quarkus.builder.BuildContext; import io.quarkus.builder.BuildStep; +import io.quarkus.commons.classloading.ClassloadHelper; import io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem; import io.quarkus.deployment.console.ConsoleCommand; import io.quarkus.deployment.console.ConsoleStateManager; @@ -408,9 +409,10 @@ public void execute(BuildContext context) { public boolean test(String s) { QuarkusClassLoader cl = (QuarkusClassLoader) Thread.currentThread() .getContextClassLoader(); + String resourceName = ClassloadHelper.fromClassNameToResourceName(s); //if the class file is present in this (and not the parent) CL then it is an application class List res = cl - .getElementsWithResource(s.replace('.', '/') + ".class", true); + .getElementsWithResource(resourceName, true); return !res.isEmpty(); } })); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/filesystem/ReloadableFileManager.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/filesystem/ReloadableFileManager.java index b203b7134b70c..f3ae3a718453b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/filesystem/ReloadableFileManager.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/filesystem/ReloadableFileManager.java @@ -1,5 +1,7 @@ package io.quarkus.deployment.dev.filesystem; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -296,7 +298,7 @@ protected Class findClass(String name) throws ClassNotFoundException { // It would be easier to call the loadClass() methods of the delegateClassLoaders // here, but we have to load the class from the bytecode ourselves, because we // need it to be associated with our class loader. - String path = name.replace('.', '/') + ".class"; + String path = fromClassNameToResourceName(name); URL url = findResource(path); if (url == null) { throw new ClassNotFoundException(name); @@ -376,4 +378,4 @@ private static byte[] read(InputStream source, int initialSize) throws IOExcepti return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); } } -} \ No newline at end of file +} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java index eca7628f8960f..d1b59bbb95935 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java @@ -1,5 +1,7 @@ package io.quarkus.deployment.dev.testing; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Modifier; @@ -654,13 +656,14 @@ public String apply(Class aClass) { Map transformedClasses = new HashMap<>(); for (String i : classesToTransform) { try { + String resourceName = fromClassNameToResourceName(i); byte[] classData = IoUtil - .readBytes(deploymentClassLoader.getResourceAsStream(i.replace('.', '/') + ".class")); + .readBytes(deploymentClassLoader.getResourceAsStream(resourceName)); ClassReader cr = new ClassReader(classData); ClassWriter writer = new QuarkusClassWriter(cr, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); cr.accept(new TestTracingProcessor.TracingClassVisitor(writer, i), 0); - transformedClasses.put(i.replace('.', '/') + ".class", writer.toByteArray()); + transformedClasses.put(resourceName, writer.toByteArray()); } catch (Exception e) { log.error("Failed to instrument " + i + " for usage tracking", e); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/index/IndexWrapper.java b/core/deployment/src/main/java/io/quarkus/deployment/index/IndexWrapper.java index 9b515259151ab..03d59b48f2d25 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/index/IndexWrapper.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/index/IndexWrapper.java @@ -1,5 +1,7 @@ package io.quarkus.deployment.index; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Modifier; @@ -313,7 +315,7 @@ static boolean index(Indexer indexer, String className, ClassLoader classLoader) return false; } try (InputStream stream = classLoader - .getResourceAsStream(className.replace('.', '/') + ".class")) { + .getResourceAsStream(fromClassNameToResourceName(className))) { if (stream != null) { indexer.index(stream); result = true; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java index 708dbb4e3c31e..5f37c1a83446d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java @@ -1,5 +1,6 @@ package io.quarkus.deployment.pkg.steps; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; import static io.quarkus.deployment.pkg.PackageConfig.JarConfig.JarType.*; import java.io.BufferedInputStream; @@ -649,7 +650,7 @@ private JarBuildItem buildThinJar(CurateOutcomeBuildItem curateOutcomeBuildItem, fastJarJarsBuilder.setGenerated(generatedZip); try (FileSystem out = createNewZip(generatedZip, packageConfig)) { for (GeneratedClassBuildItem i : generatedClasses) { - String fileName = i.getName().replace('.', '/') + ".class"; + String fileName = fromClassNameToResourceName(i.getName()); Path target = out.getPath(fileName); if (target.getParent() != null) { Files.createDirectories(target.getParent()); @@ -1181,7 +1182,7 @@ private void copyCommonContent(FileSystem runnerZipFs, Map> } } for (GeneratedClassBuildItem i : generatedClasses) { - String fileName = i.getName().replace('.', '/') + ".class"; + String fileName = fromClassNameToResourceName(i.getName()); seen.put(fileName, "Current Application"); Path target = runnerZipFs.getPath(fileName); handleParent(runnerZipFs, fileName, seen); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/AdditionalClassLoaderResourcesBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/AdditionalClassLoaderResourcesBuildStep.java index 9f07f98382cc5..2b1a8fbdf8d5c 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/AdditionalClassLoaderResourcesBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/AdditionalClassLoaderResourcesBuildStep.java @@ -1,5 +1,7 @@ package io.quarkus.deployment.steps; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -31,7 +33,7 @@ void appendAdditionalClassloaderResources(BuildProducer archives = cl.getElementsWithResource(classFileName); if (!archives.isEmpty()) { ClassPathElement classPathElement = archives.get(0); @@ -195,7 +197,7 @@ public byte[] apply(String className, byte[] originalBytes) { } } } - String classFileName = className.replace('.', '/') + ".class"; + String classFileName = fromClassNameToResourceName(className); List archives = cl.getElementsWithResource(classFileName); if (!archives.isEmpty()) { ClassPathElement classPathElement = archives.get(0); @@ -372,7 +374,7 @@ private byte[] transformClass(String className, List extractGeneratedResources(BuildResult buildRe Map data = new HashMap<>(); for (GeneratedClassBuildItem i : buildResult.consumeMulti(GeneratedClassBuildItem.class)) { if (i.isApplicationClass() == applicationClasses) { - data.put(i.getName().replace('.', '/') + ".class", i.getClassData()); + data.put(fromClassNameToResourceName(i.getName()), i.getClassData()); if (BootstrapDebug.DEBUG_CLASSES_DIR != null) { try { File debugPath = new File(BootstrapDebug.DEBUG_CLASSES_DIR); diff --git a/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/BannerProcessorTest.java b/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/BannerProcessorTest.java index 77a2ff63770e8..37a61aa51272b 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/BannerProcessorTest.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/BannerProcessorTest.java @@ -1,5 +1,6 @@ package io.quarkus.deployment.pkg.steps; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -40,7 +41,7 @@ public void checkQuarkusCoreBannerOnFilesystemWithSpecialCharacters(@TempDir Pat } try (final FileSystem fs = ZipUtils.newFileSystem(zipPath)) { - Path classFile = fs.getPath(MyBannerProcessor.class.getName().replace('.', '/') + ".class"); + Path classFile = fs.getPath(fromClassNameToResourceName(MyBannerProcessor.class.getName())); Files.createDirectories(classFile.getParent()); Files.write(classFile, "".getBytes(StandardCharsets.UTF_8)); } diff --git a/core/deployment/src/test/java/io/quarkus/deployment/util/JandexUtilTest.java b/core/deployment/src/test/java/io/quarkus/deployment/util/JandexUtilTest.java index e2b8a47b0130c..518a550c787a7 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/util/JandexUtilTest.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/util/JandexUtilTest.java @@ -16,6 +16,8 @@ import org.jboss.jandex.Type.Kind; import org.junit.jupiter.api.Test; +import io.quarkus.commons.classloading.ClassloadHelper; + public class JandexUtilTest { private static final DotName SIMPLE = DotName.createSimple(Single.class.getName()); @@ -307,7 +309,7 @@ private static Index index(Class... classes) { for (Class clazz : classes) { try { try (InputStream stream = JandexUtilTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(ClassloadHelper.fromClassNameToResourceName(clazz.getName()))) { indexer.index(stream); } } catch (IOException e) { diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/scan/QuarkusScanner.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/scan/QuarkusScanner.java index b00343709b9ad..945a92c98f17f 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/scan/QuarkusScanner.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/scan/QuarkusScanner.java @@ -1,5 +1,7 @@ package io.quarkus.hibernate.orm.runtime.boot.scan; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -149,8 +151,9 @@ public Categorization getCategorization() { @Override public InputStreamAccess getStreamAccess() { + final String resourceName = fromClassNameToResourceName(name); return new UrlInputStreamAccess( - Thread.currentThread().getContextClassLoader().getResource(name.replace('.', '/') + ".class")); + Thread.currentThread().getContextClassLoader().getResource(resourceName)); } } } diff --git a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypeInfosTest.java b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypeInfosTest.java index 10f86f00999e2..9094b70283d16 100644 --- a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypeInfosTest.java +++ b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypeInfosTest.java @@ -19,6 +19,7 @@ import org.jboss.jandex.ParameterizedType; import org.junit.jupiter.api.Test; +import io.quarkus.commons.classloading.ClassloadHelper; import io.quarkus.qute.Engine; import io.quarkus.qute.Expression; import io.quarkus.qute.deployment.TypeInfos.Info; @@ -94,8 +95,9 @@ private void assertHints(String hintStr, String... expectedHints) { private static Index index(Class... classes) throws IOException { Indexer indexer = new Indexer(); for (Class clazz : classes) { + final String resourceName = ClassloadHelper.fromClassNameToResourceName(clazz.getName()); try (InputStream stream = TypeInfosTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { indexer.index(stream); } } diff --git a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypesTest.java b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypesTest.java index 1be95694e93f2..98568867acfcf 100644 --- a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypesTest.java +++ b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/TypesTest.java @@ -19,6 +19,7 @@ import org.jboss.jandex.Type; import org.junit.jupiter.api.Test; +import io.quarkus.commons.classloading.ClassloadHelper; import io.quarkus.qute.EvalContext; import io.quarkus.qute.ValueResolver; import io.quarkus.qute.deployment.Types.AssignabilityCheck; @@ -78,8 +79,9 @@ public void testIsImplementorOf() throws IOException { private static Index index(Class... classes) throws IOException { Indexer indexer = new Indexer(); for (Class clazz : classes) { + final String resourceName = ClassloadHelper.fromClassNameToResourceName(clazz.getName()); try (InputStream stream = TypesTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { indexer.index(stream); } } diff --git a/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/FilterClassIntrospector.java b/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/FilterClassIntrospector.java index 6a161f5798e3a..fdd721de53765 100644 --- a/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/FilterClassIntrospector.java +++ b/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/FilterClassIntrospector.java @@ -1,5 +1,7 @@ package io.quarkus.resteasy.reactive.server.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -24,7 +26,8 @@ public FilterClassIntrospector(ClassLoader classLoader) { public boolean usesGetResourceMethod(MethodInfo methodInfo) { String className = methodInfo.declaringClass().name().toString(); - try (InputStream is = classLoader.getResourceAsStream(className.replace('.', '/') + ".class")) { + final String resourceName = fromClassNameToResourceName(className); + try (InputStream is = classLoader.getResourceAsStream(resourceName)) { ClassReader configClassReader = new ClassReader(is); FilterClassVisitor classVisitor = new FilterClassVisitor(methodInfo.descriptor()); configClassReader.accept(classVisitor, 0); diff --git a/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/MessageBodyWriterTransformerUtils.java b/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/MessageBodyWriterTransformerUtils.java index fabd174fc23e8..988f75fc26e5e 100644 --- a/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/MessageBodyWriterTransformerUtils.java +++ b/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/MessageBodyWriterTransformerUtils.java @@ -1,5 +1,7 @@ package io.quarkus.resteasy.reactive.server.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.util.Optional; @@ -24,7 +26,8 @@ private MessageBodyWriterTransformerUtils() { } public static boolean shouldAddAllWriteableMarker(String messageBodyWriterClassName, ClassLoader classLoader) { - try (InputStream is = classLoader.getResourceAsStream(messageBodyWriterClassName.replace('.', '/') + ".class")) { + final String resourceName = fromClassNameToResourceName(messageBodyWriterClassName); + try (InputStream is = classLoader.getResourceAsStream(resourceName)) { if (is != null) { AtomicBoolean result = new AtomicBoolean(false); ClassReader configClassReader = new ClassReader(is); diff --git a/extensions/resteasy-reactive/rest/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/IllegalClassExceptionMapper.java b/extensions/resteasy-reactive/rest/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/IllegalClassExceptionMapper.java index 8e9cd5802221b..a4f30d79703b5 100644 --- a/extensions/resteasy-reactive/rest/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/IllegalClassExceptionMapper.java +++ b/extensions/resteasy-reactive/rest/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/IllegalClassExceptionMapper.java @@ -1,5 +1,7 @@ package io.quarkus.resteasy.reactive.server.test.simple; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; @@ -78,7 +80,7 @@ public Response toResponse(IncompatibleClassChangeError exception) { private void dumpClass(String classname, String method) { InputStream bytes = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(classname.replace('.', '/') + ".class"); + .getResourceAsStream(fromClassNameToResourceName(classname)); try { ClassReader cr = new ClassReader(bytes); PrintWriter writer = new PrintWriter(System.err); diff --git a/extensions/security/deployment/src/test/java/io/quarkus/security/test/rolesallowed/ConfigExpressionDetectionTest.java b/extensions/security/deployment/src/test/java/io/quarkus/security/test/rolesallowed/ConfigExpressionDetectionTest.java index 0f8de64952245..745cd1ab9a18f 100644 --- a/extensions/security/deployment/src/test/java/io/quarkus/security/test/rolesallowed/ConfigExpressionDetectionTest.java +++ b/extensions/security/deployment/src/test/java/io/quarkus/security/test/rolesallowed/ConfigExpressionDetectionTest.java @@ -1,5 +1,7 @@ package io.quarkus.security.test.rolesallowed; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.util.HashMap; @@ -24,8 +26,9 @@ public class ConfigExpressionDetectionTest { // point here is to verify expected values gathered from @RolesAllowed annotation are detected correctly var indexer = new Indexer(); for (Class aClass : new Class[] { ConfigExpressionDetectionTest.class, ValidValues.class }) { + final String resourceName = fromClassNameToResourceName(aClass.getName()); try (InputStream stream = ConfigExpressionDetectionTest.class.getClassLoader() - .getResourceAsStream(aClass.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { assert stream != null; indexer.index(stream); } catch (IOException e) { diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeConfigTest.java b/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeConfigTest.java index c7cf0b045844b..edac2469c210b 100644 --- a/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeConfigTest.java +++ b/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/DefaultSerdeConfigTest.java @@ -41,6 +41,7 @@ import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; +import io.quarkus.commons.classloading.ClassloadHelper; import io.quarkus.deployment.builditem.GeneratedClassBuildItem; import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; @@ -146,9 +147,10 @@ Function assertStartsWith(String starts) { private static IndexView index(List> classes) { Indexer indexer = new Indexer(); for (Class clazz : classes) { + final String resourceName = ClassloadHelper.fromClassNameToResourceName(clazz.getName()); try { try (InputStream stream = DefaultSerdeConfigTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { indexer.index(stream); } } catch (IOException e) { diff --git a/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/ReflectiveClassForValueSerializerPayloadTest.java b/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/ReflectiveClassForValueSerializerPayloadTest.java index 0e1d45bee34e1..3ba622207a71c 100644 --- a/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/ReflectiveClassForValueSerializerPayloadTest.java +++ b/extensions/smallrye-reactive-messaging-kafka/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/kafka/deployment/ReflectiveClassForValueSerializerPayloadTest.java @@ -1,5 +1,6 @@ package io.quarkus.smallrye.reactivemessaging.kafka.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; @@ -332,9 +333,10 @@ void processAnnotationsForReflectiveClassJsonbPayload() { private static IndexView index(Class... classes) { Indexer indexer = new Indexer(); for (Class clazz : classes) { + final String resourceName = fromClassNameToResourceName(clazz.getName()); try { try (InputStream stream = DefaultSerdeConfigTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { indexer.index(stream); } } catch (IOException e) { diff --git a/extensions/smallrye-reactive-messaging-pulsar/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/pulsar/deployment/DefaultSchemaConfigTest.java b/extensions/smallrye-reactive-messaging-pulsar/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/pulsar/deployment/DefaultSchemaConfigTest.java index 0910e90ddd70b..cae0686c4c449 100644 --- a/extensions/smallrye-reactive-messaging-pulsar/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/pulsar/deployment/DefaultSchemaConfigTest.java +++ b/extensions/smallrye-reactive-messaging-pulsar/deployment/src/test/java/io/quarkus/smallrye/reactivemessaging/pulsar/deployment/DefaultSchemaConfigTest.java @@ -41,6 +41,7 @@ import org.reactivestreams.Subscriber; import io.quarkus.arc.deployment.SyntheticBeanBuildItem; +import io.quarkus.commons.classloading.ClassloadHelper; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem; import io.quarkus.deployment.recording.RecorderContext; @@ -136,9 +137,10 @@ String generateId(Type type, String targetType) { private static IndexView index(List> classes) { Indexer indexer = new Indexer(); for (Class clazz : classes) { + final String resourceName = ClassloadHelper.fromClassNameToResourceName(clazz.getName()); try { try (InputStream stream = DefaultSchemaConfigTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(resourceName)) { indexer.index(stream); } } catch (IOException e) { diff --git a/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ConfigPropertyBuildItemCandidateUtil.java b/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ConfigPropertyBuildItemCandidateUtil.java index fb929cc120259..dd7394ffcd2f8 100644 --- a/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ConfigPropertyBuildItemCandidateUtil.java +++ b/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ConfigPropertyBuildItemCandidateUtil.java @@ -1,5 +1,7 @@ package io.quarkus.spring.boot.properties.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -26,7 +28,8 @@ public class ConfigPropertyBuildItemCandidateUtil { */ public static void removePropertiesWithDefaultValue(ClassLoader classLoader, String configClass, List candidates) { - try (InputStream is = classLoader.getResourceAsStream(configClass.replace('.', '/') + ".class")) { + final String resourceName = fromClassNameToResourceName(configClass); + try (InputStream is = classLoader.getResourceAsStream(resourceName)) { ClassReader configClassReader = new ClassReader(is); configClassReader.accept(new ConfigClassVisitor(candidates, configClass), 0); } catch (IOException e) { diff --git a/extensions/spring-data-jpa/deployment/src/test/java/io/quarkus/spring/data/deployment/MethodNameParserTest.java b/extensions/spring-data-jpa/deployment/src/test/java/io/quarkus/spring/data/deployment/MethodNameParserTest.java index 874cab3028af2..e30104afa0862 100644 --- a/extensions/spring-data-jpa/deployment/src/test/java/io/quarkus/spring/data/deployment/MethodNameParserTest.java +++ b/extensions/spring-data-jpa/deployment/src/test/java/io/quarkus/spring/data/deployment/MethodNameParserTest.java @@ -1,5 +1,6 @@ package io.quarkus.spring.data.deployment; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -115,7 +116,7 @@ public static Index index(Class... classes) throws IOException { Indexer indexer = new Indexer(); for (Class clazz : classes) { try (InputStream stream = MethodNameParserTest.class.getClassLoader() - .getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) { + .getResourceAsStream(fromClassNameToResourceName(clazz.getName()))) { indexer.index(stream); } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/ExtensionInvoker.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/ExtensionInvoker.java index 24c4efb9d586d..bdfa4e8542ec7 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/ExtensionInvoker.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/ExtensionInvoker.java @@ -38,7 +38,7 @@ class ExtensionInvoker { extensionClasses.put(extensionClass.getName(), extensionClass); extensionClassInstances.put(extensionClass, extension); try (InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream( - extensionClass.getName().replace('.', '/') + ".class")) { + extensionClass.getName().replace('.', '/').concat(".class"))) { extensionsIndexer.index(stream); } catch (IOException e) { throw new UncheckedIOException(e); diff --git a/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java b/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java index 3879ac294bb73..c3974b21551c2 100644 --- a/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java +++ b/independent-projects/bootstrap/benchmarks/src/main/java/io/quarkus/commons/benchmarks/BenchmarkClassnameToResourceName.java @@ -1,6 +1,8 @@ package io.quarkus.commons.benchmarks; -import io.quarkus.commons.classloading.ClassloadHelper; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -12,8 +14,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -import java.io.IOException; -import java.util.concurrent.TimeUnit; +import io.quarkus.commons.classloading.ClassloadHelper; /** * We benchmark this strategy with CompilerControl.Mode.EXCLUDE as this code diff --git a/independent-projects/bootstrap/maven-resolver/pom.xml b/independent-projects/bootstrap/maven-resolver/pom.xml index 97ce31340034c..ee02443b7e1f0 100644 --- a/independent-projects/bootstrap/maven-resolver/pom.xml +++ b/independent-projects/bootstrap/maven-resolver/pom.xml @@ -33,6 +33,10 @@ + + io.quarkus + quarkus-classloader-commons + io.smallrye.beanbag smallrye-beanbag-maven diff --git a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/options/BootstrapMavenOptions.java b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/options/BootstrapMavenOptions.java index 5ef8f4297a0d4..3a2999a7da632 100644 --- a/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/options/BootstrapMavenOptions.java +++ b/independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/options/BootstrapMavenOptions.java @@ -22,6 +22,7 @@ import org.apache.maven.shared.utils.cli.CommandLineUtils; import io.quarkus.bootstrap.util.PropertyUtils; +import io.quarkus.commons.classloading.ClassloadHelper; /** * This class resolves relevant Maven command line options in case it's called @@ -256,7 +257,7 @@ private static Map invokeParser(ClassLoader cl, String[] args) t * classpath of the context classloader */ public static Path getClassOrigin(Class cls) throws IOException { - return getResourceOrigin(cls.getClassLoader(), cls.getName().replace('.', '/') + ".class"); + return getResourceOrigin(cls.getClassLoader(), ClassloadHelper.fromClassNameToResourceName(cls.getName())); } public static Path getResourceOrigin(ClassLoader cl, final String name) throws IOException { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/maven/utilities/MojoUtils.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/maven/utilities/MojoUtils.java index e7a33a355a384..b7ad89af50517 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/maven/utilities/MojoUtils.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/maven/utilities/MojoUtils.java @@ -28,6 +28,7 @@ import io.fabric8.maven.Maven; import io.fabric8.maven.XMLFormat; +import io.quarkus.commons.classloading.ClassloadHelper; /** * @author kameshs @@ -319,7 +320,7 @@ public static String[] readGavFromSettingsGradle(ByteArrayInputStream buildFileI * classpath of the context classloader */ public static Path getClassOrigin(Class cls) throws IOException { - return getResourceOrigin(cls.getClassLoader(), cls.getName().replace('.', '/') + ".class"); + return getResourceOrigin(cls.getClassLoader(), ClassloadHelper.fromClassNameToResourceName(cls.getName())); } public static Path getResourceOrigin(ClassLoader cl, final String name) throws IOException { diff --git a/test-framework/common/src/main/java/io/quarkus/test/common/PathTestHelper.java b/test-framework/common/src/main/java/io/quarkus/test/common/PathTestHelper.java index 05fda9bc7c68d..d28982f69a653 100644 --- a/test-framework/common/src/main/java/io/quarkus/test/common/PathTestHelper.java +++ b/test-framework/common/src/main/java/io/quarkus/test/common/PathTestHelper.java @@ -1,5 +1,7 @@ package io.quarkus.test.common; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.File; import java.net.MalformedURLException; import java.net.URI; @@ -133,7 +135,7 @@ private PathTestHelper() { */ public static Path getTestClassesLocation(Class testClass) { String classFileName = testClass.getName().replace('.', File.separatorChar) + ".class"; - URL resource = testClass.getClassLoader().getResource(testClass.getName().replace('.', '/') + ".class"); + URL resource = testClass.getClassLoader().getResource(fromClassNameToResourceName(testClass.getName())); if (resource.getProtocol().equals("jar")) { try { @@ -254,7 +256,7 @@ public static Path getResourcesForClassesDirOrNull(Path classesDir, String name) } public static boolean isTestClass(String className, ClassLoader classLoader, Path testLocation) { - URL resource = classLoader.getResource(className.replace('.', '/') + ".class"); + URL resource = classLoader.getResource(fromClassNameToResourceName(className)); if (resource == null) { return false; } diff --git a/test-framework/junit5-component/src/main/java/io/quarkus/test/component/QuarkusComponentTestExtension.java b/test-framework/junit5-component/src/main/java/io/quarkus/test/component/QuarkusComponentTestExtension.java index 0046c09eee626..97b3627c620e2 100644 --- a/test-framework/junit5-component/src/main/java/io/quarkus/test/component/QuarkusComponentTestExtension.java +++ b/test-framework/junit5-component/src/main/java/io/quarkus/test/component/QuarkusComponentTestExtension.java @@ -1,5 +1,7 @@ package io.quarkus.test.component; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -1196,7 +1198,7 @@ private File getTestOutputDirectory(Class testClass) { testOutputDirectory = new File(outputDirectory); } else { // org.acme.Foo -> org/acme/Foo.class - String testClassResourceName = testClass.getName().replace('.', '/') + ".class"; + String testClassResourceName = fromClassNameToResourceName(testClass.getName()); // org/acme/Foo.class -> /some/path/to/project/target/test-classes/org/acme/Foo.class String testPath = testClass.getClassLoader().getResource(testClassResourceName).getFile(); // /some/path/to/project/target/test-classes/org/acme/Foo.class -> /some/path/to/project/target/test-classes diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/AbstractJvmQuarkusTestExtension.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/AbstractJvmQuarkusTestExtension.java index 5623be978f8ef..ff12e7389a0a1 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/AbstractJvmQuarkusTestExtension.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/AbstractJvmQuarkusTestExtension.java @@ -1,5 +1,6 @@ package io.quarkus.test.junit; +import static io.quarkus.commons.classloading.ClassloadHelper.fromClassNameToResourceName; import static io.quarkus.test.common.PathTestHelper.getAppClassLocationForTestLocation; import static io.quarkus.test.common.PathTestHelper.getTestClassesLocation; @@ -77,7 +78,7 @@ protected PrepareResult createAugmentor(ExtensionContext context, Class