Error messages does not contain description in native executable in Ballerina

53 Views Asked by At

I'm trying out building native executable using GraalVM with my currently existing simple RestAPI with database connection using JDBC connector [1].

[1] https://ballerina.io/learn/graalvm-executable-overview/#build-the-graalvm-executable

The error messages printed in the stdout only shows null for the root cause as following log line.

error: Error in SQL connector configuration: Failed to initialize pool: null Caused by :null

No any errors when running the built jar file but there is an error in running native executable.

Also the following error was occurred when using h2 driver.

[[platform.java11.dependency]]
artifactId = "h2"
version = "2.0.206"
groupId = "com.h2database"

We were trying to build with mssql connector, but that build was failing at [2/7] Performing analysis... stage with attached logs. Therefore we tried using h2 driver for testing

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing java.util.Calendar$Builder.build() 
Parsing context:
   at java.util.Calendar$Builder.build(Calendar.java:1473)
   at com.microsoft.sqlserver.jdbc.SQLServerSecurityUtility.getMSIAuthToken(SQLServerSecurityUtility.java:328)
   at com.microsoft.sqlserver.jdbc.SQLServerConnection.getFedAuthToken(SQLServerConnection.java:4532)
   at com.microsoft.sqlserver.jdbc.SQLServerConnection.onFedAuthInfo(SQLServerConnection.java:4498)
   at com.microsoft.sqlserver.jdbc.SQLServerConnection.processFedAuthInfo(SQLServerConnection.java:4458)
   at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onFedAuthInfo(tdsparser.java:289)
   at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:125)
   at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:37)

    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:153)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:104)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:83)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraph(MethodTypeFlow.java:65)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultVirtualInvokeTypeFlow.java:109)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:562)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis$1.run(PointsToAnalysis.java:488)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
    at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
    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: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported type java.util.JapaneseImperialCalendar 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.
    at parsing java.util.Calendar$Builder.build(Calendar.java:1508)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2518)
    at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:110)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3393)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3345)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3190)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:97)
    at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:84)
    at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.run(Phase.java:49)
    at jdk.internal.vm.compiler/org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:446)
    at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
    at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:135)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:685)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:171)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:349)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:93)
    ... 13 more
Caused by: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported type java.util.JapaneseImperialCalendar 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.
    at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.lookup(AnnotationSubstitutionProcessor.java:140)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor$ChainedSubstitutionProcessor.lookup(SubstitutionProcessor.java:125)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor$ChainedSubstitutionProcessor.lookup(SubstitutionProcessor.java:125)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisUniverse.lookupAllowUnresolved(AnalysisUniverse.java:210)
    at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.lookupType(WrappedConstantPool.java:244)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.lookupType(BytecodeParser.java:4199)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genNewInstance(BytecodeParser.java:4493)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5291)
    at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3385)
    ... 28 more
2

There are 2 best solutions below

0
Tharmigan Krishnananthalingam On BEST ANSWER

With Ballerina SwanLake Update 8(2201.8.x), we can pass the additional build options in the build command like below:

$ bal build --graalvm --graalvm-build-options="-H:ConfigurationFileDirectories=config-dir"

Additionally, when we try to build a ballerina package with the libraries which may not be GraalVM compatible then the following warning will be printed:

WARNING: Some dependencies may not be GraalVM compatible.

If we are using external Java dependencies then the following warning will be printed:

WARNING: Package is not verified with GraalVM.

To resolve this warning, please ensure that all Java dependencies of this
package are compatible with GraalVM.

In the above scenarios, it is advisable to use the Ballerina GraalVM compatible libraries by checking the Ballerina Central. Otherwise, we have to manually find the required configurations using the tracing agent and add them to build command. More information on running a tracing agent and adding the configurations can be found in this guide.

0
Nipuna Madhushan On

The GraalVM Native image does not support java dynamic features such as reflection directly[1]. But you can add them as configuration files when building the native image. These configurations can be automatically created by using the Tracing agent[2].

[1] https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/

[2] https://www.graalvm.org/latest/reference-manual/native-image/dynamic-features/

The error message suggests that a class is not initialized for native image which ends up in a NPE. This may be due to some external driver jar which has been used in the application. Ballerina native build only supports Ballerina runtime, standard libraries, and some Ballerina external libraries. So if some external jar dependencies need to be added, we have to find the required configurations using the tracing agent and use native-image command to build the native image (Currently bal build --graalvm does not support to add additional configurations).

In this case, similar external driver dependency for mssql connector has been used as well, thats why we have encountered the above error. If we use ballerinax/mssql.driver[3] instead of that mssql driver dependency, the build should work fine.

[3] https://central.ballerina.io/ballerinax/mssql.driver


If we need to have some external drivers jars in our Ballerina application, we can approach this in multiple ways,

  1. Use all needed drivers as imports. This will add drivers to the runtime. Con is these need to be maintained even if it is unnecessary.
  2. Use drivers through Ballerina.toml.

In this case, you have to add the related configs manually.