懒人有各种各样的偷懒手段,主要是他想偷懒。

最近又扎入了阅读的深渊而不能自拔,一不小心意识到已是八月,索性就偷闲对最近开发中的Bug定位修改做个记录。

公司发展经年,已上线多个项目,有些项目也都上线了多个版本,伴随着跟破解玩家斗争的不断升级,终于在五年年前某个项目的某个版本中,开始引入了内存加密的手段,然后作为一只喜欢偷懒的程序狗,对内存加密的手段及方式一再进行升级和重构,为了达到尽可能的一劳永逸,终于在四年前进行了常用基本类型的加密封装:EncryptInt,EncrypyFloat,之后每每交付部门的各项目人员进行项目升级,于是开启了一段Bug的传奇。。。

在公司最新的项目之前(Unity4/5),项目中使用的序列化插件一直都是NewtonJson.Net,github上的开源项目,Unity商店中也有封装好的版本,当然为了偷懒的方便,前期未封装类型前(逐个重要信息加密时期),直接使用了别人上传的dll;为针对后期封装为加密类型后的偷懒,也对应的进行了插件的升级,这样插件升级后,我们即可以使用JsonConvert.DefaultSettings的方式进行加密类型数据的全局序列化设置:

1 JsonSerializerSettings tSetting = new JsonSerializerSettings();    
2 var tIntConverter = new JsonCustomIntConvert();
3 var tFloatConverter = new JsonCustomFloatConvert();
4 JsonConvert.DefaultSettings = new System.Func<JsonSerializerSettings>(() =>
5 {
6     tSetting.Converters.Add(tIntConverter);
7     tSetting.Converters.Add(tFloatConverter);
8     return tSetting;
9 });

其中JsonCustomIntConvert/JsonCustomFloatConvert为我们针对加密类型EncryptInt/EncrypyFloat定义的序列化转换器:

 1 public class JsonCustomIntConvert : JsonConverter
 2 {
 3     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 4     {
 5         if(reader.TokenType == JsonToken.Null)
 6         {
 7             return 0;
 8         }
 9         else if(reader.TokenType == JsonToken.String)
10         {
11             return (EncryptInt)int.Parse(reader.Value.ToString());
12         }
13         else if(reader.TokenType == JsonToken.Integer)
14         {
15             return (EncryptInt)Convert.ToInt32(reader.Value);
16         }
17         else
18         {
19             return 0;
20         }
21     }
22 
23     public override bool CanConvert(Type objectType)
24     {
25         return objectType == typeof(EncryptInt);
26     }
27 
28     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
29     {
30         int tValue = (EncryptInt)value;
31         writer.WriteValue(tValue);
32     }
33 }

于是问题就这么引入进来了。。

且卡顿的点应该是在进行数据存档。

下进行Bug的复现测试:

及Bug的固有性,于是将打点处的序列化改为序列化随机初始化的有50个固定数据的List,果然问题依旧,问题出在序列换的阶段。

题在递归发生之前/序列化之前),通过简单分析怀疑是泄露问题,所以针对可能的Add、Insert等进行了针对性的查找分析以及缓存修改测试,最终两方定位发现问题出在JsonSerializer.CreateDefault(settings)处,其底层实现为:

1 public static JsonSerializer CreateDefault()
2 {
3     // copy static to local variable to avoid concurrency issues
4     Func<JsonSerializerSettings> defaultSettingsCreator = JsonConvert.DefaultSettings;
5     JsonSerializerSettings defaultSettings = (defaultSettingsCreator != null) ? defaultSettingsCreator() : null;
6     
7     JsonSerializer tSerializer = Create(defaultSettings);
8     return tSerializer;
9 }

可以看到每次序列化都会操作JsonConvert.DefaultSettings,即会不断的tSetting.Converters中添加新的序列化器,从而导致泄露。只需简单修改如下即可:

1 var tIntConverter = new JsonCustomIntConvert();
2 var tFloatConverter = new JsonCustomFloatConvert();
3 JsonConvert.DefaultSettings = new System.Func<JsonSerializerSettings>(() =>
4 {
5     JsonSerializerSettings tSetting = new JsonSerializerSettings();    
6     tSetting.Converters.Add(tIntConverter);
7     tSetting.Converters.Add(tFloatConverter);
8     return tSetting;
9 });

修改后的及时测试及定期的code review不可懈怠!

相关文章:

  • 2022-12-23
  • 2021-07-21
  • 2021-08-07
  • 2022-12-23
  • 2021-07-23
  • 2022-01-19
  • 2021-09-11
  • 2021-07-23
猜你喜欢
  • 2022-12-23
  • 2021-11-14
  • 2021-06-24
  • 2022-03-07
  • 2022-12-23
  • 2022-01-12
  • 2021-05-17
相关资源
相似解决方案