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まわりのリフレクションを設定すればよさそうだけど、とりあえずこれで。