Search code examples
javajarjava-bytecode-asm

Java ASM visitMethod access 4161 meaning


I have the following inheritance structure: enter image description here

SomeModel implements Entity, and SomeModelQueryRepo has 2 methods that return SomeModel: get given an Id, and get returning all SomeModels in the repo.

For some reason, visitMethod detects another secret method: get which returns a base Entity.

However, that is not explicitly declared. The access code is a bit unusual, with a value of 4161. I tried looking at the opcodes, but I can't determine which combination leads to that value. What does 4161 mean?


Solution

  • These are the Method access and property flags.

    4161 (which is 0x1041) corresponds to this combination of flags:

    0x0001 ACC_PUBLIC
    0x0040 ACC_BRIDGE
    0x1000 ACC_SYNTHETIC
    

    The meaning of these flags is

    • The ACC_BRIDGE flag is used to indicate a bridge method generated by a compiler for the Java programming language
    • The ACC_SYNTHETIC flag indicates that this method was generated by a compiler and does not appear in source code, unless it is one of the methods named in §4.7.8.

    This combination is used by the Java Compiler if it needs to create "bridge methods": methods that are needed because of generics spezialisation / generics type erasure.

    In your case you probably have:

    public interface Entity<E> {}
    
    public class SomeModel implements Entity<Long> {}
    
    public interface QueryRepository<Id, E extends<Entity<Id>> {
        E get(Id id);
    }
    
    public class SomeModelQueryRepo implements QueryRepository<Long, SomeModel> {
        @Override
        public SomeModel get(Long id) {
            return null;
        }
    }
    

    For the class SomeModelQueryRepo to implement QueryRepository it must contain a method Entity get(Object id) because that is what the QueryRepository contains as method after type erasure.

    The compiler therefore creates this synthetic bridge method:

        public Entity<Object> get(Object id) {
            return get((Long) id);
        }