[apache/dubbo]getMethodParameter(java.lang.String, java.lang.String, java.lang.String)并发修改导致空指针异常

2024-07-02 869 views
2
Environment
  • Dubbo version: 2.7.13
  • Operating System version: Mac OS、Linux
  • Java version: 1.8
  • 方法名 org.apache.dubbo.metadata.MetadataInfo.ServiceInfo#getMethodParameter(java.lang.String, java.lang.String, java.lang.String) Steps to reproduce this issue

    出问题的代码 if (methodParams == null) { methodParams = URL.toMethodParameters(params); consumerMethodParams = URL.toMethodParameters(consumerParams); } 修改为 Map<String, Map<String, String>> temp = methodParams; if (methodParams == null) { methodParams = URL.toMethodParameters(params); if(temp == null){ try { Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } } consumerMethodParams = URL.toMethodParameters(consumerParams); }

    1. 多线程问题较难复现,采用修改代码的形式模拟
    2. 修改代码
    3. 在sleep的时间内进行两次请求,第一个请求进入sleep,第二个请求出现空指针异常

由于methodParams已经不为空,consumerMethodParams没有被初始化,执行到342行代码时发生空指针


Caused by: java.lang.NullPointerException: null
    at org.apache.dubbo.metadata.MetadataInfo$ServiceInfo.getMethodParameter(MetadataInfo.java:353)
    at org.apache.dubbo.metadata.MetadataInfo$ServiceInfo.getMethodParameter(MetadataInfo.java:344)
    at org.apache.dubbo.registry.client.InstanceAddressURL.getServiceMethodParameter(InstanceAddressURL.java:143)
    at org.apache.dubbo.registry.client.InstanceAddressURL.getMethodParameter(InstanceAddressURL.java:156)
    at org.apache.dubbo.common.URL.getMethodParameter(URL.java:881)
    at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.initLoadBalance(AbstractClusterInvoker.java:314)
    at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:263)
    at org.apache.dubbo.rpc.cluster.interceptor.ClusterInterceptor.intercept(ClusterInterceptor.java:47)
    at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$InterceptorInvokerNode.invoke(AbstractCluster.java:92)
    at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:93)
    at org.apache.dubbo.registry.client.migration.ServiceDiscoveryMigrationInvoker.invoke(ServiceDiscoveryMigrationInvoker.java:59)
    at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:96)
    at org.apache.dubbo.common.bytecode.proxy1.sayHello(proxy1.java)

回答

5

@Holmesus 能不能提供一个可以重现的测试用例呢??就像MetadataInfoTest里面的方法一样

2

@Holmesus 我想用CAS能解决这个问题。或者两个if判断

4

这个不太好复现,我用多线程只复现了一次,是通过修改MetadataInfo的源码稳定重现的,把MetadataInfo复制一份放在IDE中,用sleep让后来的线程先执行后续的代码