记一坑

同事新一项目,大概率启动出现

ConcurrentModificationException


他自己研究认为是
archaius 包冲突导致

直接把包给排除干掉


因为其他项目都是一样的依赖包,感觉问题的根源不在这,而且把这个包去掉可能会影响项目的其他功能(配置刷新)



排查的第一步还是看报错信息,报错是在HashTable里面的next方法。

大致的报错原因是因为HashTable对象中的modCount值与其迭代器快照中的值不同,简单来说就是在获取迭代器后,又对源HashTable做了修改

初看,应该是一个并发问题没跑了

接着通过断点的方式,找到了其时间范围前后对系统属性做了设置的地方(因为获取迭代器的地方,包装的就是系统属性的)
找到了两个地方

第一个地方就是同事认为有问题的
archaius
包中的
ArchaiusAutoConfiguration
    protected static void configureArchaius(
            ConfigurableEnvironmentConfiguration envConfig, ConfigurableEnvironment env,
            List<AbstractConfiguration> externalConfigurations) {
        if (initialized.compareAndSet(false, true)) {
            String appName = env.getProperty("spring.application.name");
            if (appName == null) {
                appName = "application";
                log.warn("No spring.application.name found, defaulting to 'application'");
            }
            System.setProperty(DeploymentContext.ContextKey.appId.getKey(), appName);

            ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration();

            // support to add other Configurations (Jdbc, DynamoDb, Zookeeper, jclouds,
            // etc...)
            if (externalConfigurations != null) {
                for (AbstractConfiguration externalConfig : externalConfigurations) {
                    config.addConfiguration(externalConfig);
                }
            }
            config.addConfiguration(envConfig,
                    ConfigurableEnvironmentConfiguration.class.getSimpleName());

            defaultURLConfig = new DynamicURLConfiguration();
            try {
                config.addConfiguration(defaultURLConfig, URL_CONFIG_NAME);
            }
            catch (Throwable ex) {
                log.error("Cannot create config from " + defaultURLConfig, ex);
            }

            // TODO: sys/env above urls?
            if (!Boolean.getBoolean(DISABLE_DEFAULT_SYS_CONFIG)) {
                SystemConfiguration sysConfig = new SystemConfiguration();
                config.addConfiguration(sysConfig, SYS_CONFIG_NAME);
            }
            if (!Boolean.getBoolean(DISABLE_DEFAULT_ENV_CONFIG)) {
                EnvironmentConfiguration environmentConfiguration = new EnvironmentConfiguration();
                config.addConfiguration(environmentConfiguration, ENV_CONFIG_NAME);
            }

            ConcurrentCompositeConfiguration appOverrideConfig = new ConcurrentCompositeConfiguration();
            config.addConfiguration(appOverrideConfig, APPLICATION_PROPERTIES);
            config.setContainerConfigurationIndex(
                    config.getIndexOfConfiguration(appOverrideConfig));

            addArchaiusConfiguration(config);
        }
        else {
            // TODO: reinstall ConfigurationManager
            log.warn(
                    "Netflix ConfigurationManager has already been installed, unable to re-install");
        }
    }

 


初始化的时候设置了@appId的系统属性

第二个地方是
NioEventLoop
    static {
        String key = "sun.nio.ch.bugLevel";
        String bugLevel = SystemPropertyUtil.get("sun.nio.ch.bugLevel");
        if (bugLevel == null) {
            try {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        System.setProperty("sun.nio.ch.bugLevel", "");
                        return null;
                    }
                });
            } catch (SecurityException var3) {
                logger.debug("Unable to get/set System Property: sun.nio.ch.bugLevel", var3);
            }
        }

        int selectorAutoRebuildThreshold = SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 512);
        if (selectorAutoRebuildThreshold < 3) {
            selectorAutoRebuildThreshold = 0;
        }

        SELECTOR_AUTO_REBUILD_THRESHOLD = selectorAutoRebuildThreshold;
        if (logger.isDebugEnabled()) {
            logger.debug("-Dio.netty.noKeySetOptimization: {}", DISABLE_KEY_SET_OPTIMIZATION);
            logger.debug("-Dio.netty.selectorAutoRebuildThreshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD);
        }

    }

 

 

最后通过设置默认的

sun.nio.ch.bugLevel系统属性

暂时解决了这个问题
posted @ 2021-04-19 16:49  gabin  阅读(260)  评论(0编辑  收藏  举报