sofastack / sofa-rpc

SOFARPC is a high-performance, high-extensibility, production-level Java RPC framework.
https://www.sofastack.tech/sofa-rpc/docs/Home
Apache License 2.0
3.81k stars 1.16k forks source link

Javassist does not handle interface duplication method correctly #1384

Open s2marine opened 6 months ago

s2marine commented 6 months ago

Describe the bug

Javassist reports an error when encountering duplicate method: "duplicate method". When I change default implementation of the proxy to Bytebuddy, the service starts successfully.

Expected behavior

Duplicate methods should only generate one method.

Actual behavior

Exception in thread "main" com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException: RPC-010080001: 使用 [javassist] 构造代理出现错误. 
    at com.alipay.sofa.rpc.proxy.javassist.JavassistProxy.getProxy(JavassistProxy.java:149)
    at com.alipay.sofa.rpc.proxy.ProxyFactory.buildProxy(ProxyFactory.java:50)
    at com.alipay.sofa.rpc.bootstrap.DefaultConsumerBootstrap.refer(DefaultConsumerBootstrap.java:156)
    at com.alipay.sofa.rpc.config.ConsumerConfig.refer(ConsumerConfig.java:955)
    at me.s2marine.QuickStartClient.main(QuickStartClient.java:14)
Caused by: javassist.bytecode.DuplicateMemberException: duplicate method: getType in me.s2marine.QuickStartClient$HelloService_proxy_0
    at javassist.bytecode.ClassFile.testExistingMethod(ClassFile.java:685)
    at javassist.bytecode.ClassFile.addMethod(ClassFile.java:660)
    at javassist.CtClassType.addMethod(CtClassType.java:1498)
    at com.alipay.sofa.rpc.proxy.javassist.JavassistProxy.getProxy(JavassistProxy.java:125)
    ... 4 more

Steps to reproduce

Minimal yet complete reproducer code (or GitHub URL to code)

public class QuickStartClient {

    public static void main(String[] args) {
        ConsumerConfig<HelloService> consumerConfig = new ConsumerConfig<HelloService>()
                .setInterfaceId(HelloService.class.getName()) // Specify the interface
                .setProtocol("bolt") // Specify the protocol.setDirectUrl
                .setDirectUrl("bolt://127.0.0.1:12200"); // Specify the direct connection address

        // Generate the proxy class
        HelloService helloService = consumerConfig.refer();
    }

    public interface HelloService extends SubInterface1, SubInterface2 {
        String sayHello(String string);
    }

    interface SubInterface1 {
        String getType();

        String someMethod1();
    }

    interface SubInterface2 {
        String getType();

        String someMethod2();
    }
}

Environment

nobodyiam commented 6 months ago

I'm not sure whether it's a good practice to support this scenario, is there an actual situation you encountered?

s2marine commented 6 months ago

Probably not a good coding practice for this case. It’s just that I think as a framework, it may need to support the modes which supported by JDK.

EvenLjj commented 5 months ago

@s2marine Thank you for your feedback. This issue does indeed exist here. One solution is to do logical deduplication in the method com.alipay.sofa.rpc.proxy.javassist.JavassistProxy#createMethod.If you'd like to fix it, welcome to take part in contributing.