Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoExpireCache NPE #8153

Closed
luosm opened this issue Apr 14, 2022 · 6 comments · Fixed by #8162
Closed

AutoExpireCache NPE #8153

luosm opened this issue Apr 14, 2022 · 6 comments · Fixed by #8162
Labels
area/Client Related to Nacos Client SDK area/Config
Milestone

Comments

@luosm
Copy link

luosm commented Apr 14, 2022

Describe the bug
This program has been running 15 days, and the NPE problem has occurred, and only once.

How to Reproduce
Sorry,I do not know

  • OS: [Centos]
  • Version [nacos-server 2.0.4, nacos-client 2.0.4]
  • Module [cache]
  • SDK [spring-cloud-alibaba-nacos, dubbo]

image

error message:create limit fail

java.lang.NullPointerException: null 
at com.alibaba.nacos.common.cache.decorators.AutoExpireCache.isExpire(AutoExpireCache.java:90) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.common.cache.decorators.AutoExpireCache.get(AutoExpireCache.java:51) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.common.cache.decorators.AutoExpireCache.get(AutoExpireCache.java:61) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.common.cache.decorators.SynchronizedCache.get(SynchronizedCache.java:48) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.impl.Limiter.isLimit(Limiter.java:76) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.requestProxy(ClientWorker.java:1002) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient.queryConfig(ClientWorker.java:947) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.impl.ClientWorker.getServerConfig(ClientWorker.java:397) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.NacosConfigService.getConfigInner(NacosConfigService.java:166) ~[nacos-client-2.0.4.jar:?] 
at com.alibaba.nacos.client.config.NacosConfigService.getConfig(NacosConfigService.java:94) ~[nacos-client-2.0.4.jar:?] 
at org.apache.dubbo.configcenter.support.nacos.NacosConfigServiceWrapper.getConfig(NacosConfigServiceWrapper.java:53) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.configcenter.support.nacos.NacosDynamicConfiguration.getInternalProperty(NacosDynamicConfiguration.java:234) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration.lambda$getInternalProperty$4(CompositeDynamicConfiguration.java:74) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration.iterateConfigOperation(CompositeDynamicConfiguration.java:115) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration.getInternalProperty(CompositeDynamicConfiguration.java:74) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.getProperty(Configuration.java:124) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.getProperty(Configuration.java:111) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.CompositeConfiguration.getInternalProperty(CompositeConfiguration.java:78) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.getProperty(Configuration.java:124) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.getProperty(Configuration.java:111) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.convert(Configuration.java:144) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.Configuration.getString(Configuration.java:48) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.ConfigurationUtils.getDynamicProperty(ConfigurationUtils.java:149) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.ConfigurationUtils.lambda$getCachedDynamicProperty$0(ConfigurationUtils.java:133) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.ConfigurationCache.computeIfAbsent(ConfigurationCache.java:43) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.ConfigurationUtils.getCachedDynamicProperty(ConfigurationUtils.java:133) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.common.config.ConfigurationUtils.getCachedDynamicProperty(ConfigurationUtils.java:380) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.client.migration.DefaultMigrationAddressComparator.shouldMigrate(DefaultMigrationAddressComparator.java:71) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.client.migration.MigrationInvoker.lambda$calcPreferredInvoker$4(MigrationInvoker.java:471) ~[dubbo-3.0.5.jar:3.0.5] 
at java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90) ~[?:1.8.0_251] 
at java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1812) ~[?:1.8.0_251] 
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[?:1.8.0_251] 
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499) ~[?:1.8.0_251] 
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486) ~[?:1.8.0_251] 
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_251] 
at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) ~[?:1.8.0_251] 
at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196) ~[?:1.8.0_251] 
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_251] 
at java.util.stream.ReferencePipeline.allMatch(ReferencePipeline.java:454) ~[?:1.8.0_251] 
at org.apache.dubbo.registry.client.migration.MigrationInvoker.calcPreferredInvoker(MigrationInvoker.java:471) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.client.migration.MigrationInvoker.lambda$refreshInterfaceInvoker$3(MigrationInvoker.java:457) ~[dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.integration.DynamicDirectory.invokersChanged(DynamicDirectory.java:332) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.integration.RegistryDirectory.refreshInvoker(RegistryDirectory.java:266) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.integration.RegistryDirectory.refreshOverrideAndInvoker(RegistryDirectory.java:184) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.integration.RegistryDirectory.notify(RegistryDirectory.java:162) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.support.AbstractRegistry.notify(AbstractRegistry.java:440) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.support.FailbackRegistry.doNotify(FailbackRegistry.java:371) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.support.FailbackRegistry.notify(FailbackRegistry.java:363) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.nacos.NacosRegistry.notifySubscriber(NacosRegistry.java:556) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.nacos.NacosRegistry.access$100(NacosRegistry.java:88) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.nacos.NacosRegistry$RegistryChildListenerImpl$1.doNotify(NacosRegistry.java:656) [dubbo-3.0.5.jar:3.0.5] 
at org.apache.dubbo.registry.RegistryNotifier$NotificationTask.run(RegistryNotifier.java:100) [dubbo-3.0.5.jar:3.0.5] 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_251] 
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_251] 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_251] 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_251] 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_251] 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_251] 
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_251]
@onewe
Copy link
Collaborator

onewe commented Apr 14, 2022

看了一下代码,估计是在多线程的环境下导致的

@luosm
Copy link
Author

luosm commented Apr 15, 2022

我觉得把HashMap改成ConcurrentHashMap 可能还不能解决这个问题
if (keyProp.get(key) != null && isExpire(keyProp.get(key))) {}
keyProp.get(key) != null 检查通过
其他线程调用 this.keyProp.remove(key);
然后执行 isExpire(keyProp.get(key))
这时候仍然会出现 NPE问题

如果用变量把 keyProp.get(key) 获取的值存起来,是不是可以避免NPE?

 @Override
    public V get(K key) {
        CacheItemProperties itemProperties = keyProp.get(key)
        if (itemProperties != null && isExpire(itemProperties)) {
            this.keyProp.remove(key);
            this.delegate.remove(key);
            return null;
        }
        return this.delegate.get(key);
    }

@onewe
Copy link
Collaborator

onewe commented Apr 16, 2022

直接在 isExpire 里判个空不就行了?

@KomachiSion KomachiSion added area/Config area/Client Related to Nacos Client SDK labels Apr 18, 2022
@wailin77
Copy link

bokham95gmail.com

@Oliverwqcwrw
Copy link
Contributor

直接在 isExpire 里判个空不就行了?

之前有判空,我觉得这个if不是原子操作导致的NPE

if (keyProp.get(key) != null && isExpire(keyProp.get(key))) {

@Oliverwqcwrw
Copy link
Contributor

我更新了一下PR,有时间的话可以帮忙check一下 @luosm @onewe

@KomachiSion KomachiSion added this to the 2.1.1 milestone May 20, 2022
KomachiSion pushed a commit that referenced this issue May 20, 2022
* Fix AutoExpireCache NPE

* add synchronized

* restore test

* add Null verification

* restore variable definition

* Fix NPE

* Add UT

* checkstyle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/Client Related to Nacos Client SDK area/Config
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants