Creating native executable without GraalVM installed

1.1k views Asked by At

I have a minimal project that uses an small utility class with one static method using javax.xml.transform that is called from a resource class. When trying to build a native image using: mvnw package -Pnative -Dquarkus.native.container-build=true -DskipTests I get the following error:[![com.oracle.svm.hosted.substitute.DeletedElementException][1]][1] What could be the problem and how can it be fixed ?


import java.io.StringWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

public class XmlUtils {

  public static StringBuffer transformToString(Source xmlSource, Source xslSource) {
    StringWriter writer = new StringWriter();
    try {
      Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource);
      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
      transformer.transform(xmlSource, new StreamResult(writer));
      return writer.getBuffer();
    }
    catch (Exception e) {
      e.printStackTrace();
      return null;
    }
    finally {
      try {writer.close();} catch (Exception e) {}
    }
  }
}```

  [1]: https://i.stack.imgur.com/pHt3I.png

There are several stack traces listed when fail, I included some :

com.oracle.svm.core.util.UserError$UserException: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported method java.lang.ClassLoader.defineClass1(ClassLoader, String, byte[], int, int,
ProtectionDomain, String) is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Detailed message:
Trace:
        at parsing java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
Call path from entry point to java.lang.ClassLoader.defineClass(String, byte[], int, int, ProtectionDomain):
        at java.lang.ClassLoader.defineClass(ClassLoader.java:1015)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader.defineClass(TemplatesImpl.java:207)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:514)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:551)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:584)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:818)
        at tests.XmlUtils.transformToString(XmlUtils.java:16)
        at tests.InfinispanResource.keyValue(InfinispanResource.java:25)
        at com.oracle.svm.reflect.InfinispanResource_keyValue_c2e03fbac77b9e7fcf65af2fed8d5731ce03b4f3_37.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Method.java:566)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
        at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:138)
        at org.jboss.resteasy.core.MethodInjectorImpl$$Lambda$1186/0x00000007c127d040.apply(Unknown Source)
        at sun.security.ec.XECParameters$1.get(XECParameters.java:183)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:190)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:143)
        at com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:331)
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)

        at com.oracle.svm.core.util.UserError.abort(UserError.java:79)
        at com.oracle.svm.hosted.FallbackFeature.reportAsFallback(FallbackFeature.java:217)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:765)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:555)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:468)
        at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported method java.lang.ClassLoader.defineClass1(ClassLoader
, String, byte[], int, int, ProtectionDomain, String) is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Detailed message:
Trace:
        at parsing java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
Call path from entry point to java.lang.ClassLoader.defineClass(String, byte[], int, int, ProtectionDomain):
        at java.lang.ClassLoader.defineClass(ClassLoader.java:1015)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader.defineClass(TemplatesImpl.java:207)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.defineTransletClasses(TemplatesImpl.java:514)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:551)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:584)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:818)
        at tests.XmlUtils.transformToString(XmlUtils.java:16)
        at tests.InfinispanResource.keyValue(InfinispanResource.java:25)
        at com.oracle.svm.reflect.InfinispanResource_keyValue_c2e03fbac77b9e7fcf65af2fed8d5731ce03b4f3_37.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Method.java:566)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
        at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:138)
        at org.jboss.resteasy.core.MethodInjectorImpl$$Lambda$1186/0x00000007c127d040.apply(Unknown Source)
        at sun.security.ec.XECParameters$1.get(XECParameters.java:183)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:190)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:143)
        at com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:331)
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)

        at com.oracle.graal.pointsto.constraints.UnsupportedFeatures.report(UnsupportedFeatures.java:126)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:762)
        ... 8 more
2

There are 2 answers

1
loicmathieu On

This is a GraalVM limitation, due to the nature of the native-image tool that needs to know, at native image construction time, all the code that your application will run, your application cannot define new classes.

This is explained here: https://www.graalvm.org/reference-manual/native-image/Limitations/

In your case, GraalVM native-image didn't support java.lang.ClassLoader.defineClass1.

This means that Xalan is not compatible with GraalVM native image tool.

If you want to be sure that your application only use native compatible library, be sure to use one of the Quarkus provided extensions.

Or you will need to provide substitutions for the not-running code, you can have a look at this article that explain how to create a substitution: https://blog.frankel.ch/coping-incompatible-code-graalvm-compilation/

0
Jerry On

For me, the solution was to switch to xalan-2.7.2.

I found this solution after attempting to use reflection but I couldn't run the transformation natively with JDK's javax.xml.