Jackson in native image failed to deserialize JsonNode into ConcurrentHashMap with generics

60 views Asked by At

The deserializer is defined as below, which works perfectly in a jar file running with java:

public static class Deserializer extends StdDeserializer<Subscriber> {

    public Deserializer() {
        this(null);
    }

    public Deserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Subscriber deserialize(JsonParser jp, DeserializationContext ctx)
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        if (node.isEmpty()) {
            return null;
        }

        JsonNode v = node.get("statusId");
        int id = v == null ? -1 : v.asInt(-1);
        v = node.get("name");
        String name = v == null ? null : v.asText(null);
        v = node.get("password");
        String password = v == null ? null : v.asText(null);
        ConcurrentHashMap<Integer, Account> accounts = null;
        v = node.get("accounts");
        if (v != null) {
            accounts = (new ObjectMapper()).convertValue(v,
                    new TypeReference<ConcurrentHashMap<Integer, Account>>() {
            });
        }
        return new Subscriber(id, name, password, accounts);
    }
}

But after I converted the jar file to a native image using GraalVM's native-image tool; it threw the below exception (at line convertValue) at run-time:

java.lang.IllegalArgumentException: Cannot construct instance of `java.util.concurrent.ConcurrentHashMap` (no Creators, like default constructor, exist): no default constructor found
 at [Source: UNKNOWN; byte offset: #UNKNOWN]
        at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4449)
        at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4400)
        at myclient.sub.Subscriber$Deserializer.deserialize(Subscriber.java:78)
        at myclient.sub.Subscriber$Deserializer.deserialize(Subscriber.java:46)
        at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4444)
        at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4380)

I tried to use MapType type = jsonObjectMapper.getTypeFactory().constructMapType(ConcurrentHashMap.class, Integer.class, Account.class) instead of TypeReference and it resulted in the same.

native-image --version
native-image 21.0.2 2024-01-16
GraalVM Runtime Environment Oracle GraalVM 21.0.2+13.1 (build 21.0.2+13-LTS-jvmci-23.1-b30)
Substrate VM Oracle GraalVM 21.0.2+13.1 (build 21.0.2+13-LTS, serial gc, compressed references)
1

There are 1 answers

0
zipper On

The problem is from Jackson data-bind. I reported it on Github (issue #4400). After updating to version 2.17.0-rc1, the issue is resolved.