为什么我的模式抛出空指针并传递第二个 yim

问题描述 投票:0回答:1

下面的代码存在并在

return schema.newValidator()
处抛出一个空指针,这只发生在第一次,而第二次它工作正常。而且它非常随机,每隔几个月就会在 Pod 启动时发生一次。该服务器是 Kube 管理的 spring-web 应用程序。 bean 通过 sping-context.yml 加载。

protected static final ThreadLocal<Validator> VALIDATOR = new ThreadLocal<Validator>() {
        Schema schema = null;
        protected Validator initialValue() {
            
            try {
                if (schema == null){
                    File xsdFile = PaymentCoreUtils.loadFileFromClasspath(xsdFilePath);
                    // Create SchemaFactory using XSD file
                    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
                    schema = factory.newSchema(xsdFile);
                }
            } catch (SAXException e) {}
            return schema.newValidator();
        }
    };
  1. 模式不是线程安全的,因此会导致空指针,但我无法在 JUNIT 上重现它。
  2. Schemafactory 不是线程安全的,但是 PaymentCoreUtils.loadFileFromClasspath 的实现是 return new File(PaymentCoreUtils.class.getClassLoader().getResource(file).getPath()); 这本质上是线程安全的,并且 XSD 与 JAR 一起打包,因此 XSD 在 JAR 中始终可用
  3. 检查并尝试对行中的每个语句进行多线程测试
java xml multithreading thread-safety
1个回答
0
投票

我不确定,但我肯定不会这样做。

首先,您应该只创建一个 SchemaFactory。这是一项涉及类路径搜索的昂贵操作,并且生成的工厂可以根据需要重复使用。

其次,如果您始终使用相同的架构,那么您应该只编译该架构一次,并且可以在多个线程中多次使用它进行验证。

第三,如果您重用相同的编译模式,则重用验证器没有任何好处;为每个验证事件创建一个新的验证器对象。

最后,我不了解ThreadLocal,我避免使用它,但我不信任任何具有不同步的逻辑

if (x = null) {
   initialise x
}

多线程代码中的阻塞。

© www.soinside.com 2019 - 2024. All rights reserved.