Spark FrameworkをGraalVMでネイティブコンパイルする

Spark FrameworkをGraalVMでネイティブコンパイルしてみます。

  • maven-assembly-pluginでfat jarをつくる
  • native-imageに--report-unsupported-elements-at-runtimeをつけてだまらせる


という感じで。


SparkFrameworkのdependencyを登録します。

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.8.0</version>
</dependency>


Fat Jarをつくるためにmaven-assembly-pluginを登録します

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.0</version>
        
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>kis.sparksample.MySpark</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


こんな感じの処理を書いてみます。

package kis.sparksample;

import static spark.Spark.*;

public class MySpark {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}


native-imageしてみるとエラーが出ました

jdk $GRAALVM_HOME/bin/native-image -jar $SOURCE/target/SparkSample-1.0-SNAPSHOT-jar-with-dependencies.jar 
Build on Server(pid: 92849, port: 51657)
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]    classlist:     706.16 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        (cap):   1,710.59 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        setup:   2,089.39 ms
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]     analysis:   7,770.54 ms
error: Error loading a referenced type: java.lang.reflect.InvocationTargetException
Detailed message:
Error: Error loading a referenced type: java.lang.reflect.InvocationTargetException
Trace: 
	at parsing org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:418)
Call path from entry point to org.slf4j.LoggerFactory.getILoggerFactory(): 
	at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:408)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
...


原因をみてみようと、--report-unsupported-elements-at-runtimeをつけてみます

jdk $ $GRAAL_HOME/bin/native-image --report-unsupported-elements-at-runtime -jar $SOURCE/target/SparkSample-1.0-SNAPSHOT-jar-with-dependencies.jar 
Build on Server(pid: 92849, port: 51657)
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]    classlist:     557.25 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        (cap):   1,513.05 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        setup:   1,764.90 ms
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]   (typeflow):   3,893.53 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]    (objects):   3,937.29 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]   (features):     166.68 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]     analysis:   8,284.49 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]     universe:     399.41 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]      (parse):     850.16 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]     (inline):   1,226.09 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]    (compile):   7,422.96 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]      compile:  10,158.63 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        image:   1,358.09 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]        write:     706.80 ms
[SparkSample-1.0-SNAPSHOT-jar-with-dependencies:92849]      [total]:  23,271.43 ms

通ってしまった。


動かす

jdk $ ./SparkSample-1.0-SNAPSHOT-jar-with-dependencies 


動いてしまった


サイズは15MBくらい。

jdk $ ls -l SparkSample-1.0-SNAPSHOT-jar-with-dependencies 
-rwxr-xr-x  1 kishida  staff  15266396 11 14 19:46 SparkSample-1.0-SNAPSHOT-jar-with-dependencies


SLF4Jまわりのリフレクションを設定すればよさそうだけど、とりあえずこれで。