我有一个 cfc 方法,它循环遍历列表并通过 cfhttp 进行一系列 SOAP 调用。然后将结果插入数据库。
该过程本身工作得很好,问题是java内存慢慢填满,最终(取决于返回的记录中的元素数量)停止工作。没有错误或任何可见的东西它就停止了。如果我通过 Coldfusion 管理查看应用程序日志文件,我会看到以下一个或两个错误:
GC overhead limit exceeded The specific sequence of files included or processed is:
or
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大师可以看到我的错误?
UPDATE :这是输出示例,这有助于查看内存的下降情况。
有 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 - 转储空闲内存-35条记录-总记录= 35
- 99111 - fm = 176.218482971 - 转储 freeMemory -0 条记录 - 总记录 = 0
- 100998 - fm = 194.708694458 - 转储空闲内存-185条记录-总记录= 185
- 101811 - fm = 160.61415863 - 转储freeMemory -2500条记录 - fm = 112.862670898 - 转储freeMemory -2500条记录 - fm = 86.2071380615 - 转储freeMemory -2500条记录 - fm = 52.9639358521 - 转储freeMe莫里 -1064 条记录 - 总记录 = 8564
- 105014 - fm = 56.1721343994 - 转储freeMemory -14条记录 - 总记录= 14
- 105992 - fm = 73.0022964478 - 转储freeMemory -14条记录 - 总记录= 14
- 107539 - fm = 75.9522399902 - 转储空闲内存-93条记录-总记录= 93
- 107580 - fm = 58.345199585 - 转储空闲内存-2500条记录
这并不是 Java 不能很好地管理 GC,而是你没有管理你放入(以及从内存中取出)的内容,以便垃圾收集器可以清理它们。 。你正在(试图~)治疗症状而不是问题。
查看内存中的内容以及为什么您希望进行 GC 处理的内容isn't正在接受GC教育。可能是您引用了共享范围内的内容(意外地),或者类似的内容。不过,在 Java 之上使用 ColdFusion 解决此类问题有点黑暗艺术。
但是,当您强制执行 GC 时,不要尝试“修复”事物未被 GC 的“问题”,而是解决导致内存 a) 填满的问题; b) 当您认为应该可以进行 GC 时,却不能进行 GC。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)