制作一个swf,通过IE运行它,并观察你的内存不断增长 - 甚至可能出现猛涨 - 原因似乎超出了Flash程序员的控制范围:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.media.*;
import flash.net.*;
import flash.utils.Timer;
public class HelloCam extends Sprite
{
private var m_tmr:Timer = new Timer(5000, 1);
public function HelloCam()
{
stage ? init() : addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(pEvent:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
(addChild(new Video()) as Video).attachCamera(Camera.getCamera());
m_tmr.addEventListener(TimerEvent.TIMER, onTimer);
m_tmr.start();
}
private function onTimer(pEvent:TimerEvent):void
{
removeEventListener(TimerEvent.TIMER, onTimer);
navigateToURL(new URLRequest("http://someIP/HelloCam.swf"), "_self");
}
}
}
这不是一个特定程序的孤立。我们一直在处理一个问题,该问题始于更大的软件,如果您有Camera
个对象和Video
对象,则向用户提供本地Feed,并继续执行重定向在同一个网站上,存在严重的内存泄漏。
(在某些机器上比在其他机器上更糟糕,但它就在那里。我们也看到过这样的情况,它会打到门槛,稍微回过头来,然后在没有进一步阻碍的情况下从那里飙升。)
我们尝试了几种方法,包括将浏览器包装在.NET程序中并通过.NET处理刷新,而不是通过Flash处理。我们已经切换了网站在不同刷新时会做的不同事情。所有这些。
这是Flash的核心和它的目标,所以有什么方法(希望除了使用调试swfs和Flash播放器)来阻止这样的内存泄漏,或者Adobe / Microsoft真的这么草率?
答案 0 :(得分:1)
此代码中没有任何内容会导致内存泄漏。它可能是或可能不是IE问题。虽然我觉得很奇怪你每隔5秒自己“刷新”一次应用程序,但这不是一个优雅的解决方案。
现在要真正了解泄漏的来源,您需要对SWF进行分析。我建议使用Adobe Scout ,它会为您提供详细的分析,如内存,CPU时间,垃圾收集运行等。
我认为这是您真正了解导致内存泄漏的唯一方法,因为您需要记住Flash在虚拟机中运行,因此可能是导致内存泄漏的其他SWF。此外,您每次都在重新加载应用程序并制作新相机。可能只是垃圾收集器不经常运行,并且在VM决定运行GC时,内存会被分配到某个点。
答案 1 :(得分:0)
这是一个IE问题,而不是一个Flash问题。无论是正常使用IE还是通过带有WebBrowser
对象的.NET程序,都是如此。
话虽这么说,我们遇到的代码涉及在VB.NET中使用WebBrowser
对象,我们通过.NET代码处理大部分刷新和重定向,而不是Flash代码。因此,如果你要从问题中的Flash代码中刷新,然后将它们重新定位到.NET代码中,这是一个没有内存泄漏的简短示例:
Option Explicit On
Option Strict On
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("KERNEL32.DLL", EntryPoint:="SetProcessWorkingSetSize", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Friend Shared Function SetProcessWorkingSetSize(pProcess As IntPtr, dwMinimumWorkingSetSize As Integer, dwMaximumWorkingSetSize As Integer) As Boolean
End Function
<DllImport("KERNEL32.DLL", EntryPoint:="GetCurrentProcess", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Friend Shared Function GetCurrentProcess() As IntPtr
End Function
Private Const URL As String = "http://someIP/HelloCam.swf"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ws.Url = New Uri(URL)
Timer1.Interval = 5000
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1)
ws.Url = New Uri(URL)
End Sub
End Class
诀窍是:
为Kernel32.dll
的{{1}}和SetProcessWorkingSetSize(IntPtr, Integer, Integer)
函数建立DLL导入。
重复调用GetCurrentProcess()
,或者在重定向的同时或者单独调整时间。
SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1)
传递给-1
的第二个和第三个参数,可以使该函数以特殊模式运行,该模式检查进程内存中的所有页面,然后删除被认为的那些页面不必要。通常这可能不是解决内存泄漏的最佳方法,但由于API类内部存在问题,因此在这种情况下它可能是一个好主意。
感谢Creative Magic的answer and comment,以及学习this question的答案。