其实这个错误,也有很多文章说了,但是光看文章,你还真的不一定能解决的了,所以才困扰了我很久。
第一步先说怎么定位有问题的地方,Unity编辑器其实有一个隐藏的内存泄露检测模式的功能,可以把这个错误的所在堆栈给打印出来,这里提供一段代码来启用这个功能。
using Unity.Collections;
using UnityEditor;
/// <summary>
/// 内存泄露检测模式
/// </summary>
public class LeakDetectionMode
{
[MenuItem("Jobs/内存泄漏检测/显示当前模式")]
static void ShowLeakDetection()
{
string message = string.Format("当前模式: {0}", NativeLeakDetection.Mode.ToString());
EditorUtility.DisplayDialog("内存泄漏检测模式", message, "OK");
}
[MenuItem("Jobs/内存泄漏检测/禁用")]
static void LeakDetectionDisable()
{
NativeLeakDetection.Mode = NativeLeakDetectionMode.Disabled;
}
// 验证方法会在正式方法前执行,通不过就会置灰
[MenuItem("Jobs/内存泄漏检测/禁用", true)]
static bool ValidateLeakDetectionDisable()
{
return NativeLeakDetection.Mode != NativeLeakDetectionMode.Disabled;
}
[MenuItem("Jobs/内存泄漏检测/启用")]
static void LeakDetectionEnabled()
{
NativeLeakDetection.Mode = NativeLeakDetectionMode.Enabled;
}
[MenuItem("Jobs/内存泄漏检测/启用", true)]
static bool ValidateLeakDetectionEnabled()
{
return NativeLeakDetection.Mode != NativeLeakDetectionMode.Enabled;
}
[MenuItem("Jobs/内存泄漏检测/启用堆栈跟踪")]
static void LeakDetectionEnabledWithStackTrace()
{
NativeLeakDetection.Mode = NativeLeakDetectionMode.EnabledWithStackTrace;
}
[MenuItem("Jobs/内存泄漏检测/启用堆栈跟踪", true)]
static bool ValidateLeakDetectionEnabledWithStackTrace()
{
return NativeLeakDetection.Mode != NativeLeakDetectionMode.EnabledWithStackTrace;
}
}
我们使用其中的“启用堆栈跟踪”选项,就能看到这个报错的堆栈信息了。
然后我们就可以发现,出错的地方在 UnityWebRequest 上,经过一通查询,发现最多的说法是,申请的 request 没有回收导致的内存泄露,解决方法很简单,就是添加一下 using 关键字。
就在我以为已经大功告成的时候,结果发现控制台里,这个错误依旧还在,这就叫人很无奈了。
经过一通测试和多日和代码的朝夕相处,终于发现了问题的关键。
request.uploadHandler.Dispose();
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(jsonData));
我们有的时候,会设置自己的 uploadHandler ,但是不设时,request 自己原本也有一个的,它就不会被释放了,自然是要泄露了。
且 request 在回收后,并不代表 handler 就会自动跟着一起回收的,我们需要对 request 进行相应的设置才行。
request.disposeUploadHandlerOnDispose = true;
request.disposeDownloadHandlerOnDispose = true;
request.disposeCertificateHandlerOnDispose = true;
当我们把能设置的地方设好,能回收的对象都确保回收后,之前常驻在控制台中的错误
A Native Collection has not been disposed
它终于消失掉了。