内存泄漏在cffunction内部循环cfmodule

时间:2011-01-07 16:56:00

标签: memory-leaks coldfusion coldfusion-9

Google员工,如果你有一个根目录为coldfusion.runtime.CFDummyComponent的堆转储。

2011年2月22日更新

Marc Esher of MXUnit fame found the exact same bug in a different context。他的解决方案涉及从query="name"from="1" to="#name.recordcount#" index="row"求解的查询的大循环。另一种方法是在循环中使用<cfthread>

<cfloop ...>
    <cfset threadName = "thread" & createUuid()>
    <cfthread name="#threadName#">
        <!--- do stuff --->
    </cfthread>
    <cfthread action="join" name="#threadName#">
</cfloop>

当遇到需要在循环内部执行的操作(例如查询和<cfmodule>内的<cffunction>)时,这非常有效,因此消耗的内存仅用于该迭代。

旧问题

希望别人可以确认或告诉我我做错了什么。我能够通过调用文件oom.cfm(如下所示)一致地重现运行的OOM。使用jconsole我能够看到请求消耗内存并且永远不会释放它直到完成。问题似乎是在<cfmodule>内调用<cffunction>,如果我注释掉<cfmodule>调用,则在请求运行时会收集垃圾。

ColdFusion版本:9,0,1,274733

JVM参数

java.home=C:/Program Files/Java/jdk1.6.0_18
java.args=-server  -Xms768m -Xmx768m -Dsun.io.useCanonCaches=false -XX:MaxPermSize=512m -XX:+UseParallelGC -Xbatch -Dcoldfusion.rootDir={application.home}/ -Djava.security.policy={application.home}/servers/41ep8/cfusion.ear/cfusion.war/WEB-INF/cfusion/lib/coldfusion.policy -Djava.security.auth.policy={application.home}/servers/41ep8/cfusion.ear/cfusion.war/WEB-INF/cfusion/lib/neo_jaas.policy -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=56033

测试用例

oom.cfm (这会调用下面的template.cfm - Adobe Bug #85736

<cffunction name="fun" output="false" access="public" returntype="any" hint="">
    <cfset var local = structNew()/>
    <!--- comment out cfmodule and no OOM --->
    <cfmodule template="template.cfm">
</cffunction>

<cfset size = 1000 * 200>
<cfloop from="1" to="#size#" index="idx">
    <cfset fun()>
    <cfif NOT idx mod 1000>
        <cflog file="se-err" text="#idx# of #size#">
    </cfif>
</cfloop>

template.cfm

<!--- I am empty! --->

更新#2 cfthread case from Elliott Sprehn - Adobe ColdFusion Bug #83359

<cfthread name="test">  
  <cfloop from="1" to="10000" index="i">      
    <cflog text="This is very bad.">      
    <cflock name="test" timeout="10">      
    </cflock>  
  </cfloop>  
  <!--- Sleep a very long time (10 minutes) --->  
  <cfset sleep(600000)>
</cfthread>

3 个答案:

答案 0 :(得分:5)

我之前没有碰到这个,但这就是我的想法:

每次调用cfmodule时,都会为它创建一个新的内存空间(IIRC,它与cfinclude之间的主要区别)。 因为您在函数内调用cfmodule,所以cfmodule内存空间在技术上属于该函数的内存空间。 在函数完成之前,函数的内存不受垃圾回收的影响。 结果:堆填充,并且您收到OOM错误。

我不认为调用这个内存泄漏是正确的,因为它的行为正确,并且当函数完成时,垃圾收集器可以清除该内存的保留。但是,我可以看到它可能不方便。

答案 1 :(得分:3)

遗憾的是,很多标签都存在此问题。我在cfthread中看到了这个cflock。在使用cflock的cfthread中编写一个非常长的循环循环,最终会耗尽内存。这需要很长时间,但它确实发生了。我打赌常规请求中也存在保留问题,但是你通常没有一个循环,里面有一个cflock运行数十万次,所以没有人注意到。

我很久以前就报告了这个bug,但它从来没有得到修复: http://www.elliottsprehn.com/cfbugs/bugs/83359

现在最好的解决方案是不要在这样的循环中使用cfmodule。自定义标签实际上并非用于在单个请求中调用20k次。您将要使用UDF。 cfmodule无论如何都非常昂贵,并且使用UDF的速度会明显加快。

答案 2 :(得分:0)

以下是对可能相关的Coldfusion版本9 cfc内存泄漏问题的讨论:http://forums.adobe.com/thread/1034324?start=0&tstart=0

请参阅此错误报告:https://bugbase.adobe.com/index.cfm?event=bug&id=3124148

我不相信Adobe发布了针对Verion 9.01的修复程序,但据说这个问题在版本10中已得到修复。大多数人都有解决方法(取决于他们的问题范围),这与此处描述的不同。 / p>