Search code examples
javabytecodejava-bytecode-asm

ASM BasicInterpreter IllegalStateException


I saw this question here on SO and I'm trying to compile the code from the accepted answer. Unfortunately, I'm keep getting an IllegalStateException at this part of the Code:

BasicInterpreter basic = new BasicInterpreter() {
        @Override public BasicValue newValue(Type type) {
            return type!=null && (type.getSort()==Type.OBJECT || type.getSort()==Type.ARRAY)?
                    new BasicValue(type): super.newValue(type);
        }
        @Override public BasicValue merge(BasicValue a, BasicValue b) {
            if(a.equals(b)) return a;
            if(a.isReference() && b.isReference())
                // this is the place to consider the actual type hierarchy if you want
                return BasicValue.REFERENCE_VALUE;
            return BasicValue.UNINITIALIZED_VALUE;
        }
    };

With the stack trace:

Exception in thread "main" java.lang.IllegalStateException
    at org.objectweb.asm.tree.analysis.BasicInterpreter.<init>(BasicInterpreter.java:66)
    at ConstantTracker$1.<init>(ConstantTracker.java:48)
    at ConstantTracker.<init>(ConstantTracker.java:48)
    at HelloWorld.analyze(HelloWorld.java:37)
    at HelloWorld.main(HelloWorld.java:28)

The exception is raised here in the BasicInterpreter class:

public BasicInterpreter() {
    super(/* latest api = */ ASM8);
    if (getClass() != BasicInterpreter.class) {
      throw new IllegalStateException(); // at this line
    }
  }

I tried to inherit the BasicInterpreter but I'm keep getting the same exception.

class BasicInterpreterLocal extends BasicInterpreter{} // Throws an IllegalStateException

I tried it with asm 7.*, 8.**, 9.0, but nothing works.

So what is the problem?. I couldn't found it.


Solution

  • As explained in this answer, subclasses should use the constructor accepting a library version number, to determine the compatibility level of the ASM library. It seems, version 5 of the ASM library, that the code was using initially, did not check this requirement. But you are using a newer version (8, apparently) of the library which enforces this rule.

    Change the code to

    BasicInterpreter basic = new BasicInterpreter(Opcodes.ASM5) { // <- the crucial point
        @Override public BasicValue newValue(Type type) {
            return type!=null && (type.getSort()==Type.OBJECT || type.getSort()==Type.ARRAY)?
                   new BasicValue(type): super.newValue(type);
        }
        @Override public BasicValue merge(BasicValue a, BasicValue b) {
            if(a.equals(b)) return a;
            if(a.isReference() && b.isReference())
                // this is the place to consider the actual type hierarchy if you want
                return BasicValue.REFERENCE_VALUE;
            return BasicValue.UNINITIALIZED_VALUE;
        }
    };
    

    to fix this. I will also update the other answer.