近来项目发现内存泄漏问题严重,花了两天多时间才解决
修改前,实时分析雷达图每 10 秒刷新一次,内存同时增长 2M 左右
问题主要在两个地方,第一个地方占用内存最大,修改完成后,内存的增长速度降到 每分钟增长 2M 左右,第二个地方修改完成后,现在我本机测试已经看不出明显的内存增长了
内存泄漏的原因有多种,但最主要的泄漏就是 DOM 域与 js 域相互引用以及内部函数,现在我们修改的地方也是这种情况,其实如果不是经常刷新,应该问题不大,只要重启 IE 就可以释放,但我们需要不停的刷新,所以问题比较明显.
比如下面的代码:
代码一(内部函数):
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", ClickEventHandler);
function ClickEventHandler()
{
// This closure refs element
}
}
}
//调用此函数就会发生泄漏
function SetupLeak()
{
AttachEvents(document.getElementById("LeakedDiv"));
}
代码二(dom 跟 js 相互引用):
document.createElement("");
或者:
document.createElement("");
fuction a(){...}
1. WEB-INF/pages/sim/analyse/view/sceneEventList.jsp
有两处代码需要修改,这两处代码类似,下面是其中一处的代码及修改后的代码:
原代码:
$("headerContainer").childElements().invoke("remove");
$("headerContainer").innerHTML = headerHTML;
现代码:
$("headerContainer").innerHTML = null;
$("headerContainer").innerHTML = headerHTML;
2. web/common/scrollTable.jsp
在函数 initColumnResizer(...) 中内部建了函数
原代码:
var resizeBar = document.createElement('DIV');
resizeBar.style.backgroundColor = 'transparent';
.......
resizeBar.onmouseout = function() {
this.style.cursor = 'default';
};
.......
问题主要就在类似于 resizeBar.onmouseout = function(){...} 这样的代码上,DOM 对象 resizeBar 直接定义了函数 function,此处类似的函数一共是 6 个
解决方法就是将这些函数单独拿出来,然后再引用
现代码:
在 initColumnResizer 函数外新定义函数 mouseout 等函数,如下:
function mouseout(){
.......
}
然后在 initColumnResizer 函数中原来引用这些函数的地方用下面的代码替换:
rezeBar = null;
resizeBar = document.createElement('DIV');
resizeBar.style.backgroundColor = 'transparent';
.......
resizeBar.onmouseover = mouseover;
resizeBar.onmouseout = mouseout;
resizeBar.onclick = mouseclick;
resizeBar.onmousedown = mousedown;
resizeBar.onmousemove = mousemove;
resizeBar.onmouseup = mouseup;
2008年4月30日星期三
2008年4月23日星期三
闭包函数导到 IE 内存泄漏
闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数
如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏
代码一:
<html>
<head>
<script language="JScript">
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", ClickEventHandler);
function ClickEventHandler()
{
// This closure refs element
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
function BreakLeak()
{
}
</script>
</head>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:
<html>
<head>
<script language="JScript">
function AttachEvents(element)
{
// In order to remove this we need to put
// it somewhere. Creates another ref
element.expandoClick = ClickEventHandler;
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", element.expandoClick);
function ClickEventHandler()
{
// This closure refs element
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
//释放内存
function BreakLeak()
{
document.getElementById("LeakedDiv").detachEvent("onclick",
document.getElementById("LeakedDiv").expandoClick);
document.getElementById("LeakedDiv").expandoClick = null;
}
</script>
</head>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数
如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏
代码一:
<html>
<head>
<script language="JScript">
function AttachEvents(element)
{
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", ClickEventHandler);
function ClickEventHandler()
{
// This closure refs element
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
function BreakLeak()
{
}
</script>
</head>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:
<html>
<head>
<script language="JScript">
function AttachEvents(element)
{
// In order to remove this we need to put
// it somewhere. Creates another ref
element.expandoClick = ClickEventHandler;
// This structure causes element to ref ClickEventHandler
element.attachEvent("onclick", element.expandoClick);
function ClickEventHandler()
{
// This closure refs element
}
}
function SetupLeak()
{
// The leak happens all at once
AttachEvents(document.getElementById("LeakedDiv"));
}
//释放内存
function BreakLeak()
{
document.getElementById("LeakedDiv").detachEvent("onclick",
document.getElementById("LeakedDiv").expandoClick);
document.getElementById("LeakedDiv").expandoClick = null;
}
</script>
</head>
<body onload="SetupLeak()" onunload="BreakLeak()">
<div id="LeakedDiv"></div>
</body>
</html>
闭包函数导致 IE 内存泄漏
闭包函数导到 IE 内存泄漏
闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏
代码一:
解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:
闭包函数是一个内部的函数,可以理解为函数里的函数,如下面代码一中的 ClickEventHandler 函数如果闭包函数引用了外部变量,那么,闭包函数运行完毕后,可能并不会释放该变量,于是会导致内存泄漏
代码一:
解决方法就是将闭包函数先放入一个变量,这样,当它执行完成后,它仍然在内存中存在,然后再显式地释放它,如代码二:
2008年4月8日星期二
使用开源网格计算平台-GridGain实现网格计算
From: http://blog.csdn.net/danny_xcz/archive/2007/05/24/1623536.aspx
网格计算一般分为两种:数据网格和计算网格,简单的说数据网格就是把数据分布式存储,计算网格就是将任务分解为子认为并行计算。
一个计算网格平台的作用就是将任务分解开来,交给不同的结点机器运行,然后把运行结果汇聚起来。这就是Split and Aggregate。如下图所示,一个job请求分解为三个sub-job,分别被不同的机器执行,然后把结果汇聚,返回给调用的客户。

GridGain是一个开源的java网格平台。它集成了很多现成的框架,例如
JBoss
Spring
Spring AOP
JBoss AOP
AspectJ
JGroups
GridGain有两个方法将应用程序grid化:
第一种是使用AOP
假设有一个应用
01 class BizLogic {
02 public static Result process(String param) {
03 …
04 }
05 }
06
07 class Caller {
08 public static void Main(String[] args) {
09 BizLogic.process(args[0]);
10 }
11 }
如果要把process grid化,只要简单的使用一个@Gridify的annotation即可,在Caller客户端要启动GridFactory
01 class BizLogic {
02 @Gridify(…)Here
03 public static Result process(String param) {
04 …
05 }
06 }
07
08 class Caller {
09 public static void Main(String[] args) {
10 GridFactory.start();Here
11
12 try {
13 BizLogic.process(args[0]);
14 }
15 finally {
16 GridFactory.stop();Here
17 }
18 }
19 }
这是最简单,不破坏原有业务逻辑的方法,还有一种方法如果要实现复杂些的任务分解,扩展GridifyJobAdaptor基类,实现split 和aggregate 接口
网格计算一般分为两种:数据网格和计算网格,简单的说数据网格就是把数据分布式存储,计算网格就是将任务分解为子认为并行计算。
一个计算网格平台的作用就是将任务分解开来,交给不同的结点机器运行,然后把运行结果汇聚起来。这就是Split and Aggregate。如下图所示,一个job请求分解为三个sub-job,分别被不同的机器执行,然后把结果汇聚,返回给调用的客户。

GridGain是一个开源的java网格平台。它集成了很多现成的框架,例如
JBoss
Spring
Spring AOP
JBoss AOP
AspectJ
JGroups
GridGain有两个方法将应用程序grid化:
第一种是使用AOP
假设有一个应用
01 class BizLogic {
02 public static Result process(String param) {
03 …
04 }
05 }
06
07 class Caller {
08 public static void Main(String[] args) {
09 BizLogic.process(args[0]);
10 }
11 }
如果要把process grid化,只要简单的使用一个@Gridify的annotation即可,在Caller客户端要启动GridFactory
01 class BizLogic {
02 @Gridify(…)Here
03 public static Result process(String param) {
04 …
05 }
06 }
07
08 class Caller {
09 public static void Main(String[] args) {
10 GridFactory.start();Here
11
12 try {
13 BizLogic.process(args[0]);
14 }
15 finally {
16 GridFactory.stop();Here
17 }
18 }
19 }
这是最简单,不破坏原有业务逻辑的方法,还有一种方法如果要实现复杂些的任务分解,扩展GridifyJobAdaptor基类,实现split 和aggregate 接口
订阅:
博文 (Atom)