import com.gd67.javalib.util.reflect.ReflectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class TestCallParentParentFunction {
    Logger logger = LoggerFactory.getLogger(MainTest.class);
 
    abstract class GParent{
        protected void pfun(){
            logger.info("gp.pfun");
        }
    }
    class Parent extends GParent{
        protected void pfun(){
            logger.info("p.pfun");
        }
    }
    class Child extends Parent{
        public void pfun(){
            // 创建方法类型:无参数,返回值为 void
            MethodType methodType = MethodType.methodType(void.class);
            // 获取查找器
            MethodHandles.Lookup lookup = MethodHandles.lookup();
            try {
                //否则没权限
                //no private access for invokespecial: class TestCallParentParentFunction$GParent, from TestCallParentParentFunction$Child
                if(true)
                    lookup= ReflectHelper.getFied(MethodHandles.Lookup.class,"IMPL_LOOKUP");
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            // 查找爷爷类的 method() 方法句柄,第四个参数改为当前类
            MethodHandle grandparentMethod = null;
            try {
                grandparentMethod = lookup.findSpecial(
                        GParent.class,
                        "pfun",
                        methodType,
                        GParent.class
                );
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            // 调用爷爷类的方法
            try {
                grandparentMethod.invokeExact((GParent)this);  // 输出:爷爷类的 method() 被调用?
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
    }
    public static void main(String[] args) {
        Child c= new TestCallParentParentFunction().new Child();
        c.pfun();
    }
}