8

谷歌员工,如果你有一个带有coldfusion.runtime.CFDummyComponent读取根的堆转储。

2011 年 2 月 22 日更新

MXUnit 成名的 Marc Esher 在不同的上下文中发现了完全相同的错误。他的解决方案涉及通过从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 - Adob​​e 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>

模板.cfm

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

更新 #2来自 Elliott Sprehn 的 cfthread 案例- Adob​​e 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>
4

3 回答 3

5

我以前没有遇到过这种情况,但这是我认为正在发生的事情:

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

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

于 2011-01-07T19:02:23.050 回答
3

不幸的是,这个问题体现在很多标签上。我在 cfthread 中使用 cflock 看到了这一点。在使用 cflock 的 cfthread 中编写一个非常长的运行循环,您最终会耗尽内存。这需要很长时间,但它会发生。我敢打赌,常规请求中也存在保留问题,但是通常不会有一个循环运行数十万次,并且内部有一个 cflock,因此没有人注意到。

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

目前最好的解决方案是不要在这样的循环中使用 cfmodule 。自定义标签确实不适合在单个请求中调用 20k 次。您将要改用 UDF。cfmodule 无论如何都非常昂贵,使用 UDF 会明显更快。

于 2011-01-08T10:46:32.820 回答
0

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

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

我不相信 Adob​​e 发布了 9.01 版的修复程序,但据说这个问题在 10 版中得到了修复。对于大多数人来说(取决于他们的问题的范围)都有解决方法,这与这里描述的没什么不同。

于 2012-08-02T20:04:16.727 回答