The method com.alibaba.fastjson.parser.SymbolTable.addSymbol contains a race condition

t0ybt7op  于 2021-11-27  发布在  Java
关注(0)|答案(0)|浏览(229)

Here is my test method:

@Test
    public void testRead()
    {
        try{

            Map<String,String> myMap = JSON.parseObject( new FileInputStream("resource/map.json") ,Map.class );

        }
            catch(Exception e)
            {
                e.printStackTrace();
            }
    }

The method is run by multiple threads. Here is the stack trace found by vmlens, a tool to test multithreaded java.
com/alibaba/fastjson/parser/SymbolTable.addSymbol
com/alibaba/fastjson/parser/JSONScanner.addSymbol
com/alibaba/fastjson/parser/JSONLexerBase.scanSymbol
com/alibaba/fastjson/parser/DefaultJSONParser.parseObject
com/alibaba/fastjson/parser/deserializer/MapDeserializer.deserialze
com/alibaba/fastjson/parser/deserializer/MapDeserializer.deserialze
com/alibaba/fastjson/parser/DefaultJSONParser.parseObject
com/alibaba/fastjson/JSON.parseObject
com/alibaba/fastjson/JSON.parseObject
com/alibaba/fastjson/JSON.parseObject
com/alibaba/fastjson/JSON.parseObject
com/alibaba/fastjson/JSON.parseObject
com/alibaba/fastjson/JSON.parseObject
com/vmlens/testMultithreadedJson/fastjson/FastJsonStatic.testRead

If you look at the source you see that the array symbols is accessed without synchronization:

public String addSymbol(String buffer, int offset, int len, int hash) {
        final int bucket = hash & indexMask;

        String symbol = symbols[bucket];
        if (symbol != null) {
            if (hash == symbol.hashCode() // 
                    && len == symbol.length() //
                    && buffer.startsWith(symbol, offset)) {
                return symbol;
            }

            return subString(buffer, offset, len);
        }

        symbol = len == buffer.length() //
            ? buffer //
            : subString(buffer, offset, len);
        symbol = symbol.intern();
        symbols[bucket] = symbol;
        return symbol;
    }

even so it is only one array used for all threads. It is generated in the ParserConfig class which is a singelton:

public class ParserConfig {

    public final static String DENY_PROPERTY = "fastjson.parser.deny";

    public static final String[] DENYS=readSystemDenyPropety();

    public static ParserConfig getGlobalInstance() {
        return global;
    }

    public static ParserConfig                              global      = new ParserConfig();

    private final IdentityHashMap<Type, ObjectDeserializer> derializers = new IdentityHashMap<Type, ObjectDeserializer>();

    private boolean                                         asmEnable   = !ASMUtils.IS_ANDROID;

    public final SymbolTable                                symbolTable = new SymbolTable(4096);

    ...
    }

I tested with version 1.2.17

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题