我有一个cfc方法,该方法遍历列表并通过cfhttp进行一系列SOAP调用。然后将结果插入数据库。

该过程本身运作良好,但问题在于Java内存缓慢填充,最终(取决于所返回记录中的元素数量)才停止工作。没有错误或任何可见的错误只是停止。如果我通过Coldfusion管理员查看应用程序日志文件,则会看到以下一个或两个错误:

GC overhead limit exceeded The specific sequence of files included or processed is:

要么
Java heap space The specific sequence of files included or processed is:

以下是我正在运行的代码的简化版本:
<cfsetting requesttimeout="3600">
<cfloop condition="thisPass lt 10">
    <cfscript>
        runtime = CreateObject("java","java.lang.Runtime").getRuntime();
        objSystem = CreateObject( "java", "java.lang.System" );
        soapBody = '';
        soapResponse = '';
        thisStruct = '';
        lock scope='application' type='exclusive' timeout='60' {


//This is where I am trying to manage the memory and call garbage collection


        try {
            freeMemory = runtime.freeMemory()/1024/1024;
            writeOutput("- fm = "&freeMemory);
            if (freeMemory < 200){
                objSystem.gc();
                sleep(1000);
                writeDump(' - dumping freeMemory');
             }
         }
         catch(any error) {
            writeDump(' - trying to dump GC as '&now()& ' freeMemory = '&freeMemory);
         }
         }
        </cfscript>
        <cfsavecontent variable="soapBody">
            <?xml version="1.0" encoding="utf-8"?>
            [ BUILD SOAP ENVELOP ]
        </cfsavecontent>

        <cfhttp url="[URL]" method="post" result="httpResponse"
                        timeout="600" resolveurl="false">
                <cfhttpparam type="header" name="SOAPAction" value="[URL2]" />
                <cfhttpparam type="xml" value="#trim( soapBody )#"/>
            </cfhttp>


            <cfscript>
                soapBody = "";
                soapResponse = httpResponse.fileContent;
                soapResponse = xmlParse( soapResponse );
                thisStruct = xmlSearch(soapResponse,'/soap:Envelope/soap:Body/')[1].xmlChildren[1].xmlChildren[1].xmlChildren;
                writeOutput("-"&arrayLen(thisStruct)&' records');
                getPageContext().getOut().flush();
                if(arrayLen(thisStruct) == 2500){
                    thisPass = thisPass+1;
                } else {
                    writeOutput("- total records = "&(2500*(thisPass-1))+arrayLen(thisStruct));
                    thisPass = 100; // since looping while thisPass lt 10 this should prevent the next iteration
                }
            </cfscript>

            <cfloop from="1" to="#arrayLen(thisStruct)#" index="i">
                [RUN PROC TO INSERT RECORDS]
            </cfloop>
        </cfloop>

GC有时似乎会释放一些内存,但没有任何可靠性。我知道GC()仅是Java释放一些未使用的内存的建议,但是我不确定如何将其强制释放内存。某处可能有泄漏,但我没有看到。我希望这是我已经忽略的显而易见的事情,并且我承认我的Java知识非常有限。

是否有一些Java专家可以看到我的错误?

更新:这是输出示例,以防内存不足。

有236个列表可供浏览
  • 88185-fm = 293.564407349 -6条记录-总记录= 6条
  • 88389-fm = 290.86995697 -116条记录-总记录= 116
  • 88390-fm = 308.382568359 -262条记录-总记录= 262
  • 88839-fm = 292.707099915 -2032条记录-总记录= 2032
  • 91088-fm = 290.711753845 -6条记录-总记录= 6条
  • 92998-fm = 287.754066467 -5条记录-总记录= 5
  • 95510-fm = 309.919425964 -91条记录-总记录= 91
  • 96478-fm = 292.035064697 -1180条记录-总记录= 1180
  • 96479-fm = 259.001213074 -1113条记录-总记录= 1113
  • 96480-fm = 261.121406555 -110条记录-总记录= 110
  • 96796-fm = 267.235244751 -2条记录-总记录= 2
  • 96799-fm = 265.037582397 -0条记录-总记录= 0
  • 97435-fm = 263.589103699 -2500记录-fm = 227.629760742 -2500记录-fm = 200.85987854 -2500记录-fm = 202.156776428 -2500记录-fm = 166.366210938-转储freeMemory -656记录-总记录= 10656
  • 98173-fm = 160.579734802-转储freeMemory -35条记录-总记录= 35
  • 99111-fm = 176.218482971-转储freeMemory -0条记录-总记录= 0
  • 100998-fm = 194.708694458-转储freeMemory -185条记录-总记录= 185
  • 101811-fm = 160.61415863-转储freeMemory -2500记录-fm = 112.862670898-转储freeMemory -2500记录-fm = 86.2071380615-转储freeMemory -2500记录-fm = 52.9639358521-转储freeMemory -1064记录-总记录= 8564
  • 105014-fm = 56.1721343994-转储freeMemory -14条记录-总记录= 14
  • 105992-fm = 73.0022964478-转储freeMemory -14条记录-总记录= 14
  • 107539-fm = 75.9522399902-转储freeMemory -93条记录-总记录= 93
  • 107580-fm = 58.345199585-转储freeMemory -2500条记录
  • 最佳答案

    这不是Java无法很好地管理GC的情况,而是您没有以某种方式管理要放入(或从〜取出)内存的内容,以至于垃圾收集器可以清理它们。您正在(尝试〜)对待症状而不是这里的问题。

    看一下内存中将要存储的内容,以及为什么您期望被GC的内容没有被GC的原因。可能是因为您在一个共享范围内(意外地)引用了某些东西,或者类似的东西。但是,在Java之上使用ColdFusion对此类问题进行故障排除有点不明智。

    但是,当您强制执行GC时,请勿尝试“解决”未发生GC的“问题”,请解决导致内存不足的问题。 b)在您认为应该是GC时不可用。

    08-03 22:31