IdentityHashMap的put不是线程安全的, 里面的注解也写着"// 并发是处理时会可能导致缓存丢失,但不影响正确性".
也就是put后不能保证一定能写上, 但SerializeConfig.getObjectWriter里有很多对IdentityHashMap的put然后get相同key的操作, 并发会导致get可能得不到刚刚put的结果, 导致可能返回null而触发空指针异常!
触发异常的位置是: ObjectFieldSerializer.writeValue里的runtimeInfo.fieldSerializer.write, fieldSerializer实际可能是null.
6条答案
按热度按时间bpsygsoo1#
能做个testcase复现问题吗
w6mmgewl2#
我觉得这已经是很明显的bug, 虽然复现难度非常大.
但有亿万分之一的概率出错的可能, 作为一个广泛推广的开源库难道也是不该考虑的么?
另外像这种写法, 由于没有voletile或其它保护, 乱序执行会导致先执行下面那行赋值,后执行entry.next的赋值也是可能的(包括cpu cache在不同核心的同步问题),更容易导致get不到.
k10s72fa3#
我觉得这里就老老实实用ConcurrentHashMap就可以了, Class类的equals并没有重写, 用IdentityHashMap也没什么好处.
gv8xihay4#
安全的,这里没问题,得不到重新Put一次不影响后续使用哈。
laximzn55#
如果缓存拿不到就会直接重新new一个,只是会变慢一点。
6mw9ycah6#
重新new是没问题, 但关键是new的对象就put到map里, 然后后面不是返回这个new的对象, 而是又从map中get了一次,然后就没有判空了(见SerializeConfig.java的getObjectWriter(Class<?> clazz, boolean create)函数的最后几行)