micrometer icon indicating copy to clipboard operation
micrometer copied to clipboard

Native image config for netty in statsd module is not relocated during shading

Open edudar opened this issue 2 years ago • 7 comments

statsd module uses a shaded netty that makes its packages io.micrometer.shaded.io.netty, and none of the standard native hints apply.

So far, I had to add (using spring-native) the following to get the app to start at least:

@NativeHint( // Micrometer
        types = @TypeHint(
                access = {TypeAccess.DECLARED_CLASSES, TypeAccess.DECLARED_CONSTRUCTORS, TypeAccess.DECLARED_METHODS},
                typeNames = "io.micrometer.shaded.io.netty.buffer.AbstractByteBufAllocator"
        )
)
@NativeHint(
        types = {
                @TypeHint(
                        typeNames = "io.micrometer.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
                        fields = @FieldHint(name = "producerLimit", allowUnsafeAccess = true)
                ),
                @TypeHint(
                        typeNames = "io.micrometer.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
                        fields = @FieldHint(name = "consumerIndex", allowUnsafeAccess = true)
                ),
                @TypeHint(
                        typeNames = "io.micrometer.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
                        fields = @FieldHint(name = "producerIndex", allowUnsafeAccess = true)
                ),
                @TypeHint(
                        typeNames = "io.micrometer.shaded.io.netty.util.ReferenceCountUtil",
                        methods = @MethodHint(name = "touch", parameterTypes = {Object.class})
                )
        }
)

But I might have to add more as I keep testing it.

edudar avatar Jun 09 '22 17:06 edudar

I suspect we could add some build configuration to rename things in the netty native-image.properties that are in the published micrometer-registry-statsd JAR. I tried a few things with the shadow plugin but I haven't been successful so far. I don't know if that would be sufficient or not, but it seems like a good starting point. Pull request welcome.

shakuzen avatar Jul 06 '22 06:07 shakuzen

I'm told the latest native-image config for netty 4 is located at https://github.com/oracle/graalvm-reachability-metadata/tree/master/metadata/io.netty. I'm still not sure the most maintainable way to use that and ensure it is up-to-date given our shading (and repackaging) of netty. We essentially need a copy of that config using our io.micrometer.shaded.io.netty package. Though we may only need a small subset in reality, given the parts of netty that we use (via reactor-netty) in the statsd module.

shakuzen avatar Sep 14 '22 08:09 shakuzen

Hello

I think I have the similar issue. I try to use spring boot 3 native support.

And get the following issue:

Caused by: java.lang.IllegalArgumentException: Can't find '[toLeakAwareBuffer]' in io.micrometer.shaded.io.netty.buffer.AbstractByteBufAllocator
        at io.micrometer.shaded.io.netty.util.ResourceLeakDetector.addExclusions(ResourceLeakDetector.java:596) ~[na:na]
        at io.micrometer.shaded.io.netty.buffer.AbstractByteBufAllocator.<clinit>(AbstractByteBufAllocator.java:37) ~[service:1.10.2]  

not sure how to fix it with RuntimeHintsRegistrar

eye-dee avatar Dec 20 '22 10:12 eye-dee

+1, I am on SB 3.0 and can't see an easy path from these NativeHint annotations in OP to the new method of adding the "hints" as @eye-dee mentions

AlexeiZenin avatar May 08 '23 21:05 AlexeiZenin

Just for the record, it's fairly similar to annotations from spring-native. This is the registrar class I ended up creating to support SB3, statsd, and native image:

public class MicrometerHints implements RuntimeHintsRegistrar {

    public static final String NETTY_PKG = "io.micrometer.shaded.io.netty.";
    public static final String JC_TOOLS_PKG = "util.internal.shaded.org.jctools.";

    @Override
    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
        hints.reflection()
                .registerType(AbstractByteBufAllocator.class,
                        builtWith(DECLARED_CLASSES, INVOKE_PUBLIC_CONSTRUCTORS, INVOKE_DECLARED_METHODS))
                .registerType(ReferenceCountUtil.class,
                        hint -> hint.withMethod("touch", List.of(TypeReference.of(Object.class)), INVOKE))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.BaseMpscLinkedArrayQueueColdProducerFields",
                        hint -> hint.withField("producerLimit"))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.BaseMpscLinkedArrayQueueConsumerFields",
                        hint -> hint.withField("consumerIndex"))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.BaseMpscLinkedArrayQueueProducerFields",
                        hint -> hint.withField("producerIndex"))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.MpscArrayQueueConsumerIndexField",
                        hint -> hint.withField("consumerIndex"))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.MpscArrayQueueProducerIndexField",
                        hint -> hint.withField("producerIndex"))
                .registerTypeIfPresent(classLoader,
                        NETTY_PKG + JC_TOOLS_PKG + "queues.MpscArrayQueueProducerLimitField",
                        hint -> hint.withField("producerLimit"));
    }
}

edudar avatar Dec 08 '23 08:12 edudar

@edudar where is this class coming from? Do you have a reproducer for this issue?

marcingrzejszczak avatar Dec 27 '23 14:12 marcingrzejszczak

Which class? MicrometerRuntimeHints? That’s the result of trial and error trying to compile and run a service using micrometer with statsd in a native image. I don’t have a minimal reproducer, but this is a common problem with aot/native and shaded packages as classes move and are missing reachability metadata, unless one provides it.

edudar avatar Dec 27 '23 16:12 edudar