jboss-javassist / javassist

Java bytecode engineering toolkit

Home Page:www.javassist.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Replacing a method call to a private static function of an outer class from within an inner class leads to NoSuchMethodError

SamuelMotal opened this issue · comments

Hello,
I think I encountered a bug in Javassist.
The problem is reproducable with the following code snippet:

package org.example;




public class TestClass{

    static {
        System.out.println("static block 1");
    }

    static {
        System.out.println("static block 2");
    }

    enum TEST{
        TEST1,TEST2,TEST3;
    }

    private final int x;
    private final int y;
    public TestClass(){
        super();
        x=10;
        y=10;
    }

    private static void print(){
        System.out.println("hello");
    }
    public void run() {
        TEST t = TEST.TEST1;

        switch (t){
            case TEST1:
                System.out.println("test1");
                break;
            case TEST2:
                System.out.println("test2");
                break;
            case TEST3:
                System.out.println("test3");
                break;
            default:
                throw new RuntimeException("error");
        }
        new MyInnerClass().isX0();
    }

    private class MyInnerClass {
        private final int x;

        private MyInnerClass(){
            x=0;
        }

        public boolean isX0(){
            print();
            return x==0;
        }
    }

}

If in the given example code the method call to print() within MyInnerClass is replaced via the use of ExpressionEditor it leads reproduceable to a NoSuchMethodError when running the code afterwards. An Exception will look like this:

java.lang.NoSuchMethodError: 'void jforecaster.testData.TestClass.access$1()'
	at jforecaster.testData.TestClass$MyInnerClass.isX0(TestClass.java:56)
	at jforecaster.testData.TestClass.run(TestClass.java:45)
	at jforecaster.testData.CoverageTest.test_coverage(CoverageTest.java:10)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:105)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:94)
	at jforecaster.codeCoverage.RunWithCoverage.main(RunWithCoverage.java:25)

To replace the method call the following logic was used:

        final String statement=  newStatement+"{$_= $proceed($$);}";
        @Override
	public void edit(final MethodCall e) throws CannotCompileException {
	    	e.replace(statement);
	}

JDK: 17
Javassist: 3.30.2-GA

Please let me know if you can reproduce this error, if I did do something wrong, or if you need additional information which of course I am happy to provide if possible.

Kind regards,
Samuel

P.S. Thanks a lot for the great library you provide!