0

I'm using spring native to build a native-image with graalvm, i want to find all classes that implements a specific interface I tried using Reflections but it didn't work, i used spring's ClassPathScanningCandidateComponentProvider too :

It works fine when i run it as a jar file, but when i try to run the native-image .exe file it does not find any classes

this is my code

String[] basePackages = {"com.demo","com.demo2"};
    Set<Class<? extends Initializer>> subClasses = new HashSet<>();
    ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
    scanner.addIncludeFilter(new AssignableTypeFilter(Initializer.class));
    for (String basePackage : basePackages) {
        Set<?> classes = scanner.findCandidateComponents(basePackage).stream().peek(l->System.out.println(l)).collect(Collectors.toSet());
        subClasses.addAll((Set<Class<? extends Initializer>>) classes);
    }

PS : the class SubscriberRegistration implements the interface Initializer and my reflect.json file :

[ {
"name" : "com.demo.projectinstallerparent.SubscriberRegistration",
"methods": [
  { "name": "<init>", "parameterTypes": [] }
]}]
  • I'm not a graalvm expert, but a search of their docs does indicate that additional action/configuration is required when you use reflection or reflection-adjacent functionality: https://www.graalvm.org/22.1/reference-manual/native-image/Reflection/ This could also be a matter of the native-image compiler just not including those classes because they're not referred to explicitly. You might need to use some of the techniques discussed here: https://www.graalvm.org/22.1/reference-manual/native-image/BuildConfiguration/#assisted-configuration-of-native-image-builds – Gus Jul 21 '22 at 16:00
  • @Gus yes i already added a reflection configuration, that's what's my reflect.json file is for, but still not working – mdecherif Jul 21 '22 at 16:27

1 Answers1

0

You might try to execute your scanner code at image build time rather than runtime. This way, it will run on JVM with all dynamic features enabled. The resulting set of classes will be incorporated into the native image.

To execute code at image build time, just make it part of the static initializer of some class used by your app, e.g.

public class App {
    static final Set<Class<?>> INITIALIZERS = // ... your code here
}

BTW your code scans packages com.demo and com.demo2 while the class you register is in package com.demo.projectinstallerparent -- can that be the reason it is not found?

peterz
  • 306
  • 1
  • 3
  • i need to get these classes at runtime to execute some methods while deploying the app not at build time, also the package com.demo.projectinstallerparent is considered as the same as com.demo cause when i run the app as a jar whith the same code it gives me the correct result the problem exist only while executing it as a native-image – mdecherif Jul 22 '22 at 08:03
  • I'm afraid it is not possible for a native image to discover classes at runtime. Unlike JVM, a native image cannot load classes from jars or .class files (it has no bytecode interpreter). Reflection is only possible for classes configured at image build time -- those classes get compiled into the image. So a native image will only be able to "discover", via reflection, those classes that were configured at build time, which sort of defeats the point. – peterz Jul 22 '22 at 11:33