Open anshu-zs opened 6 months ago
Hi @anshu-zs,
Thanks for reaching out to us!
I wanted to let you know that there's a compatibility issue between ClassGraph and GraalVM. When compiling to Native Image with GraalVM, the JARs on the classpath are no longer available. This means that any metadata associated with resources in those files becomes invalid.
Hi @anshu-zs,
Thanks for reaching out to us!
I wanted to let you know that there's a compatibility issue between ClassGraph and GraalVM. When compiling to Native Image with GraalVM, the JARs on the classpath are no longer available. This means that any metadata associated with resources in those files becomes invalid.
Hi @selhagani Thank you for replying, So is there any workaround for this?
Hi @anshu-zs, I understand your concern. Currently, there aren't any workarounds available for this situation. However, I'll take this opportunity to forward your feedback as a feature request to our team. Thank you for bringing this to our attention!
One of our latest PRs should help with explaining what to do. We will also write a guide for this kind of cases for the next release.
In this concrete case I would include --initialize-at-build-time=ClassScanner
and all follow-up classes that are in the ScanResult
. Now note that this will likely make a very large image so you might need to also compute your queries at build time to reduce image size. For example, instead of scanResult
you can store the result of findAllClassesImplementingInterfaces
to a static field.
Hi @vjovanov I'm already following the guidelines mentioned:
native-image --no-fallback -H:ConfigurationFileDirectories=/Users/raramuri/Desktop/Anshu/rocket/rocket-examples/src/main/resources/META-INF/native-image --initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback,io.netty,examples.http.controller.ProductController,io.github.classgraph,nonapi.io.github.classgraph,examples.http.Main,com.zopsmart.rocket.engine.scanner.ClassScanner -H:+ReportUnsupportedElementsAtRuntime -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime -H:+AllowJRTFileSystem -H:Class=examples.http.Main -jar rocket-examples-0.31.0.jar
Here is modified ClassScanner class
static {
scanResult =
new ClassGraph()
.enableAnnotationInfo()
.enableMethodInfo()
.enableFieldInfo()
.scan();
System.out.println("Scanner:" + scanResult.getClassesImplementing(IEngine.class));
}
I am basically trying to print the result of scanResult.getClassesImplementing(IEngine.class)
For version GraalVM CE 22.3.1, 22.3.3 I'm getting this output while building native image
========================================================================================================================
GraalVM Native Image: Generating 'rocket-examples-0.31.0' (executable)...
========================================================================================================================
Scanner:[@lombok.Generated public class com.zopsmart.rocket.engine.ApiMappingEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.BeanFactoryEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.ConfigEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.DependencyEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.HealthEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.KeyEngine implements public abstract com.zopsmart.rocket.engine.IEngine, public class com.zopsmart.rocket.engine.MetricsEngine implements public abstract com.zopsmart.rocket.engine.IEngine, @lombok.Generated public class com.zopsmart.rocket.engine.ServerEngine implements public abstract com.zopsmart.rocket.engine.IEngine, @lombok.Generated public class com.zopsmart.rocket.engine.TracerEngine implements public abstract com.zopsmart.rocket.engine.IEngine]
Warning: Could not register io.netty.handler.codec.marshalling.MarshallingEncoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: org/jboss/marshalling/ByteOutput.
Warning: Could not register io.netty.handler.codec.compression.Lz4FrameDecoder: queryAllPublicMethods for reflection. Reason: java.lang.NoClassDefFoundError: net/jpountz/lz4/LZ4Exception.
.....
PS: Observe the result stored in Scanner but eventually I end up with this error -> mentioned in https://github.com/oracle/graal/issues/8883
Error: java.util.concurrent.ExecutionException: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: type is not available in this platform: com.oracle.svm.hosted.NativeImageSystemClassLoader
For other versions (eg: graalvm-jdk-21.0.2+13.1) My scanner result is empty
========================================================================================================================
GraalVM Native Image: Generating 'rocket-examples-0.31.0' (executable)...
========================================================================================================================
Scanner:[]
The first error comes from the fact that the scanner pulled in native image classes. In later versions on GraalVM this should not happen.
In the second snippet, the issue is that the used class loader does not see the classes from the application. Can you try to pass the ClassScanner.class.getClassLoader()
as the class loader to the ClassGraph
.
I noticed that since upgrading to GraalVM for JDK 22, you've encountered a new error. The error message suggests using the 'onlyWith' field in the TargetClass annotation to make substitution active only when necessary. It might be beneficial to review how your substitution-related annotations are configured. To provide more specific assistance, I really need a concise reproducer for the issue. Thanks!
@selhagani for which example? Can you post an error?
The first error comes from the fact that the scanner pulled in native image classes. In later versions on GraalVM this should not happen.
In the second snippet, the issue is that the used class loader does not see the classes from the application. Can you try to pass the
ClassScanner.class.getClassLoader()
as the class loader to theClassGraph
.
Hi @vjovanov I tried adding classLoader to classgraph
public class ClassScanner {
private static ScanResult scanResult;
static {
scanResult =
new ClassGraph()
.addClassLoader(ClassScanner.class.getClassLoader())
.enableAnnotationInfo()
.enableMethodInfo().enableFieldInfo().scan();
System.out.println("Scanner:" + scanResult.getClassesImplementing(IEngine.class));
}
public Set<Class> findAllClassesImplementingInterfaces(Class interfaceName) {
Set<Class> classSet = new HashSet<>();
ClassInfoList classInfos = scanResult.getClassesImplementing(interfaceName);
for (ClassInfo clazz : classInfos) {
classSet.add(clazz.loadClass());
}
System.out.println("ScanResult: "+classSet);
return classSet;
}
}
and tried creating the native image using latest Graal VM: GraalVM CE 22.0.1+8.1, but still I got the Scanner as empty along with the error
Warning: The option '-H:ReflectionConfigurationResources=META-INF/native-image/io.grpc.netty.shaded.io.netty/netty-transport/reflection-config.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:IncludeResources=application\.properties' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:IncludeResources=application\.conf' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:IncludeResources=application\.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:IncludeResources=.*Driver\.properties' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:DynamicProxyConfigurationResources=META-INF/native-image/com.datastax.oss/java-driver-core/proxy.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:+ReportUnsupportedElementsAtRuntime' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:ReflectionConfigurationResources=META-INF/native-image/com.datastax.oss/java-driver-core/reflection.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:IncludeResources=reference\.conf' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:+AllowJRTFileSystem' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: The option '-H:ReflectionConfigurationResources=META-INF/native-image/io.netty/netty-transport/reflection-config.json' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: Please re-evaluate whether any experimental option is required, and either remove or unlock it. The build output lists all active experimental options, including where they come from and possible alternatives. If you think an experimental option should be considered as stable, please file an issue.
========================================================================================================================
GraalVM Native Image: Generating 'rocket-examples-0.31.0' (executable)...
========================================================================================================================
Scanner:[]
[1/8] Initializing... (0.0s @ 0.27GB)
Error: Substitution target for org.wildfly.common.Substitutions$Target_GraalDirectives is not loaded. Use field `onlyWith` in the `TargetClass` annotation to make substitution only active when needed.
------------------------------------------------------------------------------------------------------------------------
1.0s (21.1% of total time) in 45 GCs | Peak RSS: 0.97GB | CPU load: 4.27
========================================================================================================================
Failed generating 'rocket-examples-0.31.0' after 4.1s.
Hey @vjovanov, apologies for the confusion! It seems I responded to the wrong issue that @anshu-zs has also shared and mentioned this issue in. My comment was meant for that issue not this one. Thanks for your understanding!
I noticed that since upgrading to GraalVM for JDK 22, you've encountered a new error. The error message suggests using the 'onlyWith' field in the TargetClass annotation to make substitution active only when necessary. It might be beneficial to review how your substitution-related annotations are configured. To provide more specific assistance, I really need a concise reproducer for the issue. Thanks!
I looked into this and it seems that ClassGraph
does not see the classpath when it is scanning, however it can load all the classes with the correct class loader. The only solution I found was to add the following line:
new ClassGraph().overrideClasspath("<image-builder-classpath>")
and the results showed up.
@olpaw do we have a way to fetch image-builder-classpath
from the static initializer? Also, do you know what is the reason that we deleted java.class.path
at build time?
@anshu-zs I would try to ask a question on the classgraph
issue tracker or mailing list to see why it does not see the path of the NativeImageClassLoader
.
sure @vjovanov , thanks for the help. please do let me know about the classgraph issue whenever you find anything
Hi I am trying to initialize
ClassScanner
at build time, but it's not able to load classesHere is my classScanner:
ClassScanner usage
Here are the logs when I run the native image:
Here as u can see my scanResult shows empty array
When I run my application locally instead of running native image I get scanResult as
GraalVM version GraalVM JDK 21