Git Product home page Git Product logo

vertx-graalvm-native-image-test's Introduction

Vert.x GraalVM - Native Image Test

This is a basic test project which uses GraalVM / Substrate VM VM to build a native image of a Vert.x Web application.

How to build

I prepared and tested the build only on Linux but it should also work on other platforms.

  1. Build a shaded jar of your application
  2. Run the native-image tool from GraalVM to generate the executable

The build.sh file contains more details about needed arguments.

Patches

In this test project I patched a few Vert.x and Netty classes to avoid imports related to native transports and SSL. Otherwise the image could not be build.

Vert.x Transport

First I needed to patch the io.vertx.core.net.impl.transport.Transport class in order to prevent the loading of EPoll and KQueue native support. Otherwise Substrate VM will try to load these classes and fail.

public class Transport {
…
  /**
   * The native transport, it may be {@code null} or failed.
   */
  public static Transport nativeTransport() {
    // Patched: I remove the native transport discovery. 
    // The imports would be picked up by substrate 
    // and cause further issues. 
    return null;
  }
…
}

Netty SSL

Native SSL support is another problematic area. I created a patched dummy io.netty.handler.ssl.ReferenceCountedOpenSslEngine class in order to prevent Substrate VM from digging deeper into the SSL code of Netty.

Netty Reflections

Next we need to set up the reflection configuration within reflectconfigs/netty.json.

Netty uses reflection to instantiate the socket channels. This is done in the ReflectiveChannelFactory. We need to tell Substrate VM how classes of type NioServerSocketChannel and NioSocketChannel can be instantiated.

[
  {
    "name" : "io.netty.channel.socket.nio.NioSocketChannel",
    "methods" : [
      { "name" : "<init>", "parameterTypes" : [] }
    ]
  },
  {
    "name" : "io.netty.channel.socket.nio.NioServerSocketChannel",
    "methods" : [
      { "name" : "<init>", "parameterTypes" : [] }
    ]
  }
]

Limitations

Native EPoll, KQueue support, SSL is not yet working.

Related issue: oracle/graal#353

Blog post

More information can also be found in my post on the Vert.x blog.

vertx-graalvm-native-image-test's People

Contributors

jotschi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vertx-graalvm-native-image-test's Issues

java.lang.ClassNotFoundException: io.vertx.core.logging.SLF4JLogDelegateFactory

Hi Jotschi,

Currently I try to get involved with graal and tried your example. The only difference is, that I used the released version of graal (19.1.1) and vert.x 3.8.0. The build worked fine, but this issue is raised at startup:

$ ./vertx-graalvm-native-image-test-0.0.1-SNAPSHOT
Exception in thread "main" java.lang.ExceptionInInitializerError
        at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:290)
        at java.lang.Class.ensureInitialized(DynamicHub.java:451)
        at de.jotschi.examples.Runner.main(Runner.java:18)
Caused by: java.lang.IllegalArgumentException: Error instantiating transformer class "io.vertx.core.logging.SLF4JLogDelegateFactory"
        at io.vertx.core.logging.LoggerFactory.initialise(LoggerFactory.java:54)
        at io.vertx.core.logging.LoggerFactory.<clinit>(LoggerFactory.java:32)
        at com.oracle.svm.core.hub.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:350)
        at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:270)
        ... 2 more
Caused by: java.lang.ClassNotFoundException: io.vertx.core.logging.SLF4JLogDelegateFactory
        at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
        at java.lang.ClassLoader.loadClass(Target_java_lang_ClassLoader.java:131)
        at io.vertx.core.logging.LoggerFactory.initialise(LoggerFactory.java:51)
        ... 5 more

Since you are the only one, which is using the logger-factory, mybe you have an idea, what the source could be?

Thx,
Nikolas

Failure compiling with Docker image for Graal 1.0.0.rc-9

Hello, I am trying to compile the example using Graal Docker image (https://gist.github.com/lordofthejars/d4e1f7e180ab9e518deb039f75122aa0) But I am getting exceptions regarding the usage of ByteBuffer

rror: unsupported features in 2 methods
Detailed message:
Error: Detected a direct/mapped ByteBuffer in the image heap. A direct ByteBuffer has a pointer to unmanaged C memory, and C memory from the image generator is not available at image run time. A mapped ByteBuffer references a file descriptor, which is no longer open and mapped at run time. The object was probably created by a class initializer and is reachable from a static field. By default, all class initialization is done during native image building.You can manually delay class initialization to image run time by using the option --delay-class-initialization-to-runtime=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Trace: 	object io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledDirectByteBuf
	object io.netty.buffer.UnreleasableByteBuf
	method io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(ChannelHandlerContext, Object, long, List)
Call path from entry point to io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(ChannelHandlerContext, Object, long, List):
	at io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(HttpObjectEncoder.java:195)
	at io.netty.handler.codec.http.HttpObjectEncoder.encode(HttpObjectEncoder.java:168)
	at io.netty.handler.codec.http.HttpClientCodec$Encoder.encode(HttpClientCodec.java:167)
	at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:88)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
	at io.netty.channel.AbstractChannelHandlerContext.access$1900(AbstractChannelHandlerContext.java:38)
	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081)
	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070)
	at io.netty.util.concurrent.GlobalEventExecutor$TaskRunner.run(GlobalEventExecutor.java:240)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
	at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:479)
	at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:199)
	at com.oracle.svm.core.code.CEntryPointCallStubs.com_002eoracle_002esvm_002ecore_002eposix_002ethread_002ePosixJavaThreads_002epthreadStartRoutine_0028com_002eoracle_002esvm_002ecore_002ethread_002eJavaThreads_0024ThreadStartData_0029(generated:0)
Error: Detected a direct/mapped ByteBuffer in the image heap. A direct ByteBuffer has a pointer to unmanaged C memory, and C memory from the image generator is not available at image run time. A mapped ByteBuffer references a file descriptor, which is no longer open and mapped at run time. The object was probably created by a class initializer and is reachable from a static field. By default, all class initialization is done during native image building.You can manually delay class initialization to image run time by using the option --delay-class-initialization-to-runtime=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Trace: 	object io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledDirectByteBuf
	object io.netty.buffer.UnreleasableByteBuf
	method io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(ChannelHandlerContext, Object, long, List)
Call path from entry point to io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(ChannelHandlerContext, Object, long, List):
	at io.netty.handler.codec.http.HttpObjectEncoder.encodeChunkedContent(HttpObjectEncoder.java:195)
	at io.netty.handler.codec.http.HttpObjectEncoder.encode(HttpObjectEncoder.java:168)
	at io.netty.handler.codec.http.HttpClientCodec$Encoder.encode(HttpClientCodec.java:167)
	at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:88)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
	at io.netty.channel.AbstractChannelHandlerContext.access$1900(AbstractChannelHandlerContext.java:38)
	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1081)
	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1070)
	at io.netty.util.concurrent.GlobalEventExecutor$TaskRunner.run(GlobalEventExecutor.java:240)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
	at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:479)
	at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:199)
	at com.oracle.svm.core.code.CEntryPointCallStubs.com_002eoracle_002esvm_002ecore_002eposix_002ethread_002ePosixJavaThreads_002epthreadStartRoutine_0028com_002eoracle_002esvm_002ecore_002ethread_002eJavaThreads_0024ThreadStartData_0029(generated:0)

Which version did you use at that time? I tried with rc8 and rc7 and similar failures.

Thank you very much.

Add License

Hiya! This is great stuff! Would it be possible to add license under Apache 2?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.