Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

2.5.0 Regression: java.lang.VerifyError #47

Closed
huxi opened this issue Jan 2, 2015 · 5 comments
Closed

2.5.0 Regression: java.lang.VerifyError #47

huxi opened this issue Jan 2, 2015 · 5 comments
Milestone

Comments

@huxi
Copy link

huxi commented Jan 2, 2015

The code below works with jackson/afterburner 2.4.4 but fails with 2.5.0. I think this is caused by FooBase being just an interface.

java.lang.VerifyError: (class: xxx/FooBase$Access4JacksonDeserializer, method: objectSetter signature: (Ljava/lang/Object;ILjava/lang/Object;)V) Illegal type in constant pool
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2663)
    at java.lang.Class.getConstructor0(Class.java:3067)
    at java.lang.Class.newInstance(Class.java:408)
    at com.fasterxml.jackson.module.afterburner.deser.PropertyMutatorCollector.buildMutator(PropertyMutatorCollector.java:111)
    at com.fasterxml.jackson.module.afterburner.deser.DeserializerModifier.updateBuilder(DeserializerModifier.java:61)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:231)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:405)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:354)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:262)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:242)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:439)
    at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3664)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3556)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576)

The interface that is (de)serialized:

public interface FooBase
    extends Cloneable
{
    String getId();
    void setId(String id);

    String getRevision();
    void setRevision(String revision);

    String getCategory();
    void setCategory(String category);

    Map<String, String> getAttributes();
    void setAttributes(Map<String, String> attributes);

    Set<String> getTags();
    void setTags(Set<String> tags);

    FooBase clone() throws CloneNotSupportedException;
}

The mixin for the above interface:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = FooImpl1.class, name = "impl1"),
    @JsonSubTypes.Type(value = FooImpl2.class, name = "impl2"),
    @JsonSubTypes.Type(value = FooImpl3.class, name = "impl3") })
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public abstract class FooBaseMixIn
{
    @JsonProperty("_id")
    abstract String getId();

    @JsonProperty("_id")
    abstract void setId(String id);

    @JsonProperty("_rev")
    abstract void setRevision(String revision);

    @JsonProperty("_rev")
    abstract String getRevision();
}

The module:

public class FooModule extends SimpleModule
{
    private static final long serialVersionUID = -8868552500546628519L;

    public FooModule()
    {
        super("Foo", Version.unknownVersion());
        setMixInAnnotation(FooBase.class, FooBaseMixIn.class);
    }
}

The test init:

ObjectMapper result = new ObjectMapper();
result.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
result.setDateFormat(new ISO8601DateFormat());
result.registerModule(new FooModule());
result.registerModule(new AfterburnerModule());
mapper = result;

The actual test:

FooImpl1 item = new FooImpl1();
String string = mapper.writeValueAsString(item);
if(logger.isDebugEnabled()) logger.debug("JSON-String: {}", string);
FooBase read = mapper.readValue(string, FooBase.class);
if(logger.isDebugEnabled()) logger.debug("Read item: {}", read);
assertEquals(item, read);
@huxi
Copy link
Author

huxi commented Jan 2, 2015

Oh, and removing the AfterburnerModule fixes the tests with 2.5.0.

@cowtowncoder
Copy link
Member

On plus side, I can reproduce this with simplified setup (direct annotations instead of mix-ins).
Will see what gives.

cowtowncoder added a commit that referenced this issue Jan 3, 2015
@cowtowncoder
Copy link
Member

Odd. Yes, it looks like existence of method in base interface causes issues; if those are commented out, there is no problem. So perhaps signature is incorrectly constructed using method in interface or something.

cowtowncoder added a commit that referenced this issue Jan 3, 2015
@cowtowncoder
Copy link
Member

Ok finally found the root cause: it's with new ASM visitors, and different calls (INVOKEDYNAMIC vs INVOKEINTERFACE) for setters. Was correctly handled for getters (more common to have interface there I guess), but not for setters yet.

@cowtowncoder cowtowncoder added this to the 2.2.1 milestone Jan 3, 2015
@huxi
Copy link
Author

huxi commented Jan 3, 2015

That was fast. Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants