
大家好,又见面了,我是你们的朋友全栈君。
问题重现:
我们有个方法 通过 attrKey 查询 List ,同时方法中有缓存,会优先查询缓存,没有读库,然后 写缓存 返回。
方法伪代码如下:
public ConfAttr getConf(String attrKey) {
// 从 缓存查询
List<ConfAttr> attrValues = cacheClient.get(attrKey);
if(attrValues !=null && !attrValues.isEmpty(){
return attrValues.get(0);
}
// 读库
List<ConfAttr> attrValues = selectFromDb(attrKey);
cacheClient.put(attrKey,attrValues, cacheSeconds);
return attrValues.get(0);
}然后某天业务迭代 ConfAttr类增加 source 属性。上线后 redis 反序列化出错。错误内容如下:
Exception in thread "main" java.lang.RuntimeException: Reading from a byte array threw an IOException (should never happen).
at io.protostuff.IOUtil.mergeFrom(IOUtil.java:54)
at io.protostuff.ProtostuffIOUtil.mergeFrom(ProtostuffIOUtil.java:104)
at com.cm.cache.serialize.ProtostuffSerializer.deserialize(ProtostuffSerializer.java:34)
at com.cm.cache.redis.ShardedRedisClient.get(ShardedRedisClient.java:88)
at com.test.RedisTest.main(RedisTest.java:51)
Caused by: io.protostuff.ProtobufException: CodedInput encountered an embedded string or bytes that misreported its size.
at io.protostuff.ProtobufException.misreportedSize(ProtobufException.java:86)
at io.protostuff.ByteArrayInput.readString(ByteArrayInput.java:438)
at io.protostuff.runtime.RuntimeUnsafeFieldFactory$9$1.mergeFrom(RuntimeUnsafeFieldFactory.java:753)
at io.protostuff.runtime.RuntimeSchema.mergeFrom(RuntimeSchema.java:466)
at io.protostuff.runtime.ObjectSchema.readObjectFrom(ObjectSchema.java:693)
at io.protostuff.runtime.IdStrategy$8.mergeFrom(IdStrategy.java:503)
at io.protostuff.ByteArrayInput.mergeObjectEncodedAsGroup(ByteArrayInput.java:518)
at io.protostuff.ByteArrayInput.mergeObject(ByteArrayInput.java:490)
at io.protostuff.runtime.IdStrategy$10.mergeFrom(IdStrategy.java:583)
at io.protostuff.runtime.IdStrategy$10.mergeFrom(IdStrategy.java:528)
at io.protostuff.runtime.ObjectSchema.readObjectFrom(ObjectSchema.java:590)
at io.protostuff.runtime.ObjectSchema.mergeFrom(ObjectSchema.java:350)
at io.protostuff.ByteArrayInput.mergeObjectEncodedAsGroup(ByteArrayInput.java:518)
at io.protostuff.ByteArrayInput.mergeObject(ByteArrayInput.java:490)
at io.protostuff.runtime.RuntimeUnsafeFieldFactory$15$1.mergeFrom(RuntimeUnsafeFieldFactory.java:1217)
at io.protostuff.runtime.RuntimeSchema.mergeFrom(RuntimeSchema.java:466)
at io.protostuff.IOUtil.mergeFrom(IOUtil.java:45)
... 4 more问题答案
正确答案1: 可以使用@Tag 注解 指定字段顺序。
错误答案1: 将新增的字段加载java bean 类 的末尾 就可以避免该问题了(但是实际上这种还是存在错误的可能 ,具体参考 下一节的原理分析),
PS: 这次出问题 是因为 把sourceid 加入到 属性定义的中间了。
基于错误答案1的尝试截图
改动前:

改动后:

说明
方法入口
入口 io.protostuff.runtime.RuntimeSchema#fill
static void fill(Map<String, java.lang.reflect.Field> fieldMap,
Class<?> typeClass)
{
if (Object.class != typeClass.getSuperclass())
fill(fieldMap, typeClass.getSuperclass());
for (java.lang.reflect.Field f : typeClass.getDeclaredFields())
{
int mod = f.getModifiers();
if (!Modifier.isStatic(mod) && !Modifier.isTransient(mod) && f.getAnnotation(Exclude.class) == null)
fieldMap.put(f.getName(), f);
}
}调用图

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/139827.html原文链接:https://javaforall.cn