Of the three Java embedded web servers, Tomcat, Jetty, and Undertow, which one worked with GraalVM?

Do you know GraalVM? It is a tool that natively compiles Java and, in some cases, reduces memory consumption to 1/16 (https://qiita.com/ukiuni@github/items/2999acf26fdc0c3f8353). However, there are restrictions on the applications that GraalVM can compile, and not all Java applications can be compiled natively.

This time, in order to create a native web application, I tried to verify whether a Java application with a built-in web server can be compiled and executed with GraalVM.

Enforcement

Create Fat Jar using gradle shadow and compile with Fat Jar specified by -jar option in GraalVM's native-image command.

environment

$ native-image --version
GraalVM Version 1.0.0-rc13
$ java -version
openjdk version "1.8.0_202"
OpenJDK Runtime Environment (build 1.8.0_202-20190206132754.buildslave.jdk8u-src-tar--b08)
OpenJDK GraalVM CE 1.0.0-rc13 (build 25.202-b08-jvmci-0.55, mixed mode)

Tomcat(tomcat-embed-core v9.0.17) It was no good.

Source

Source excerpt


public static void main(String[] args) throws Exception {
	Tomcat tomcat = new Tomcat();
	tomcat.setPort(8080);
	tomcat.getConnector();
	File base = new File("src/main/static/");
	Context context = tomcat.addContext("/app", base.getAbsolutePath());
	Tomcat.addServlet(context, "default", new DefaultServlet()).addMapping("/");

	Tomcat.addServlet(context, "hello", new HttpServlet() {
		protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			Writer w = resp.getWriter();
			w.write("Hello, World!");
			w.flush();
		}
	}).addMapping("/hello");
	tomcat.start();
	tomcat.getServer().await();
}

Compilation failed.

$ native-image  -jar build/libs/app-all.jar
Build on Server(pid: 2099, port: 50704)
[app-all:2099]    classlist:   1,259.46 ms
[app-all:2099]        (cap):   1,512.61 ms
[app-all:2099]        setup:   7,054.04 ms
[app-all:2099]     analysis:  10,298.20 ms
Error: unsupported features in 2 methods
Detailed message:
Error: Class initialization failed: com.sun.naming.internal.ResourceManager$AppletParameter
Original exception that caused the problem: java.lang.ExceptionInInitializerError
...(abridgement)

Sorry.

Jetty(jetty-server v9.4.15.v20190215) I was able to go!

Source excerpt


public static void main(String[] args) throws Exception {
	Server server = new Server(8080);

	server.setHandler(new AbstractHandler() {

		@Override
		public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
			response.setContentType("text/plain");
			response.setStatus(HttpServletResponse.SC_OK);
			PrintWriter out = response.getWriter();
			out.println("Hello World!");
			baseRequest.setHandled(true);
		}
	});

	server.start();
	server.join();
}

Compile & Run

$ native-image -jar build/libs/app-all.jar
Build on Server(pid: 2523, port: 51183)*
[app-all:2523]    classlist:   3,325.81 ms
[app-all:2523]        (cap):   1,309.95 ms
[app-all:2523]        setup:   8,400.08 ms
2019-04-04 22:16:54.214:INFO::ForkJoinPool-2-worker-3: Logging initialized @22713ms to org.eclipse.jetty.util.log.StdErrLog
[app-all:2523]   (typeflow):  11,805.43 ms
[app-all:2523]    (objects):   9,466.98 ms
[app-all:2523]   (features):     354.09 ms
[app-all:2523]     analysis:  37,080.95 ms
[app-all:2523]     universe:     650.05 ms
[app-all:2523]      (parse):   3,276.85 ms
[app-all:2523]     (inline):   6,226.93 ms
[app-all:2523]    (compile):  31,668.53 ms
[app-all:2523]      compile:  57,307.38 ms
[app-all:2523]        image:   2,385.43 ms
[app-all:2523]        write:     859.86 ms
[app-all:2523]      [total]: 145,307.12 ms
$ ./app-all
2019-04-04 22:19:55.501:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2019-02-15T16:53:49.381Z; git: eb70b240169fcf1abbd86af36482d1c49826fa0b; jvm 1.8.0_202
2019-04-04 22:19:55.502:INFO:oejs.AbstractConnector:main: Started ServerConnector@6b64b5db{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2019-04-04 22:19:55.502:INFO:oejs.Server:main: Started @2ms

Start up safely! I was able to access it with a browser! great.

Undertow(undertow-core v2.0.19.Final) It was no good. .. ..

Source excerpt


public static void helloWorldHandler(HttpServerExchange exchange) {
	exchange.getResponseHeaders().add(Headers.CONTENT_TYPE, "text/plain");
	exchange.getResponseSender().send("Hello World!");
}

public static void main(String[] args) {
	Undertow server = Undertow.builder().addHttpListener(8080, "0.0.0.0", App::helloWorldHandler).build();
	server.start();
}

compile.

$ native-image -jar build/libs/app-all.jar
Build on Server(pid: 2523, port: 51183)
[app-all:2523]    classlist:   2,361.03 ms
[app-all:2523]        (cap):   1,720.81 ms
[app-all:2523]        setup:   7,458.13 ms
[app-all:2523]     analysis:   6,485.28 ms
Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: org.osgi.framework.FrameworkUtil. To diagnose the issue you can use the --allow-incomplete-classpath option. The missing type is then reported at run time when it is accessed the first time.

After that, I added the --allow-incomplete-classpath option or something, but I couldn't compile it. Sorry.

So the correct answer was Jetty.

There was a result that even one could be compiled. The light of Web application operation with 1/16 memory resources has come into view! After that, if JPA works, it seems that you can make a simple Web application. JPA seems to be running on Quarkus, so I'm hoping that it can be compiled.

Recommended Posts

Of the three Java embedded web servers, Tomcat, Jetty, and Undertow, which one worked with GraalVM?
Graph the sensor information of Raspberry Pi in Java and check it with a web browser
Comparison of WEB application development with Rails and Java Servlet + JSP
[Probably the easiest] WEB application development with Apache Tomcat + Java Servlet
Install Java and Tomcat with Ansible
[Updated December 2018] Tips for embedded web server and servlet created with Jetty9
I tried to measure and compare the speed of GraalVM with JMH
About the mechanism of the Web and HTTP
I want to control the start / stop of servers and databases with Alexa
Build Apache and Tomcat environment with Docker. By the way, Maven & Java cooperation
Hello World with Java Servlet and JSP (Easy web server startup with Maven + Jetty)