tracker issue : CF-3124148

select a category, or use search below
(searches all categories and all time range)
Title:

Objects can't be garbage collected during a request

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/

Reporter/Name(from Bugbase): Jonas Meller / Jonas Meller (Jonas Meller)

Created: 02/27/2012

Components: Performance

Versions: 9.0.1

Failure Type: Memory Leak

Found In Build/Fixed In Build: 9.0.1 /

Priority/Frequency: Major / Some users will encounter

Locale/System: English / Windows 7

Vote Count: 4

Problem Description:
You run out of memory if you create too many objects in one request even if you don't keep a reference to all those objects. This happens because ColdFusion keeps references to them all. The references are held in a private variable called dummyCompMap in getPageContext().getFusionContext().

I have run into this in an application that occasionally creates a lot of beans.


Steps to Reproduce:
Create the following two files and execute run.cfm.

TenMB.cfc:
<cfcomponent output="false">
	<cffunction name="init" access="public" output="false" returntype="TenMB">
		<cfset variables.byteArray = CreateObject('java','java.lang.reflect.Array').newInstance(CreateObject('java', 'java.lang.Byte').TYPE, 10000000) />
		<cfreturn this />
	</cffunction>
</cfcomponent>

run.cfm:
<cfloop from="1" to="1000" index="i">
	<cfset CreateObject('component', 'TenMB').init() />
	<cflog file="bug" text="i: #i#" />
</cfloop>
DONE


Actual Result:
java.lang.OutOfMemoryError: Java heap space


Expected Result:
DONE


Any Workarounds:

Workaround 1:
Each thread created with cfthread gets its own FusionContext so objects created in a thread are released when the thread finishes.

run_workaround1.cfm:
<cfloop from="1" to="1000" index="i">
	<cfset threadName = CreateUUID() />
	<cfthread action="run" name="#threadName#">
		<cfset CreateObject('component', 'TenMB').init() />
	</cfthread>
	<cfthread action="join" name="#threadName#" />
	<cflog file="bug" text="i: #i#" />
</cfloop>
DONE

Workaround 2:
Get access to dummyCompMap and clear it. I don't know what the side effects are.

run_workaround2.cfm:
<cfloop from="1" to="1000" index="i">
	<cfset CreateObject('component', 'TenMB').init() />
	<cfset fusionContext = getPageContext().getFusionContext() />
	<cfset field = fusionContext.getClass().getDeclaredField('dummyCompMap') />
	<cfset field.setAccessible(true) />
	<cfset field.set(fusionContext, JavaCast('null', 0)) />
	<cflog file="bug" text="i: #i#" />
</cfloop>
DONE

----------------------------- Additional Watson Details -----------------------------

Watson Bug ID:	3124148

External Customer Info:
External Company:  
External Customer Name: J_M_84
External Customer Email:

Attachments:

  1. February 27, 2012 00:00:00: 1_bug.zip

Comments:

This is an issue for all long running requests (scheduled tasks typically).
Vote by External U.
20554 | February 27, 2012 06:38:53 AM GMT
The Server Monitor was completely disabled.
Comment by External U.
20547 | February 27, 2012 10:17:04 AM GMT
This issue has already been fixed in CF 10. Closing it.
Comment by Rupesh K.
20548 | March 04, 2012 09:42:32 AM GMT
Hi, Can you please reopen this bug? I do not agree that the fact that its fixed in coldfusion 10, is a fix. Im working for a company who just moved to coldfusion 9, and will not move to coldfusion 10 anytime soon, its a lot of work. I think its a pretty major bug (not releasing memory at cfc creation is a HUGE memory leak) This deserves a version 9 fix.
Comment by External U.
20549 | July 12, 2012 02:34:20 PM GMT
Rupesh Kumar, I hope you will reconsider you decision to close the issue after it's been fixed in CF 10. You should leave it open until it is fixed for CF 9.0.1. After all, 9.0.1 is the version for which the issue is reported!
Comment by External U.
20550 | July 13, 2012 01:52:47 AM GMT
+1. This is probably sufficiently important to consider a hotfix for CF9, even if it's already fixed in CF10.
Vote by External U.
20555 | July 13, 2012 02:45:13 AM GMT
Please fix this, this is a serious memory leak. Batch processing with cfc's within one request is hardly possible like this.
Vote by External U.
20556 | July 13, 2012 06:06:00 AM GMT
Hi, I fully agree that this bug should be solved for CF9. In my company, we've just upgraded from CF8 to CF9 and we now have a lot of memory problem ! Thanks in advance Stephane
Comment by External U.
20551 | August 09, 2012 07:22:25 AM GMT
This is a serious bug that causes poor website performance and leads to unsatisfied website visitors. Please fix ASAP.
Vote by External U.
20557 | April 25, 2013 10:52:12 AM GMT
I'm kind of curious: why does everyone consider this a "leak"? The code shown is creating a large number of instances. Those will (like any variables) be held as "in use" by CF until the end of the request, and therefore can't be GCed while the request is running. I also notice that the createobject within the loop never saves its instance. Are people assuming that somehow CF should regard it as "no longer accessible" because of that, and therefore release it after each loop iteration? I suppose we could assume it would. I'm curious, Rupesh: is that what changed? And has anyone here yet run this code on a CF10 instance (on the same box, OS, and with same heap size) to confirm that 10 "fixes" this? One might also ask: why create a new instance over and over? Might some in a situation like this be better served by saving the instance and calling its method(s) in the loop instead? I do see that in this case it's intentionally calling init. Still, that's just a convention. It is just another method in the CFC. I wonder if this "leak" would go away if instead one CFC instance was created outside the loop and only the method was called within it. And same with the chained createobjects within the init itself. Do those really need to be created anew on each instantiation of the CFC? I do realize the last two points may not work for everyone, but let's not overlook them as a possible solution for some readers of this. It seems a fairly obscure example. Let's also note that the CFC is called tenmb. Are we saying that each instance creates a 10meg object, by those java object references? And is everyone who is commenting here really doing something like that? I'd find it hard to believe. But assuming they are not, are you creating thousands of large objects in a single request? And ou are surprise that uses a lot of memory? ;-} Let me just conclude by commenting that some people may be pointed to this as a possible explanation for seeming "memory leaks" they have with CF. In my 7 years of doing CF server troubleshooting (after 6 years of working with it as a developer and trainer), I'll say that I have nearly always found that most such "leaks" turn out instead to be examples of something holding memory BEYOND the life of a request, such as large use of the session/application/server scopes, query caching, ehcaching, and so on. Do be sure to consider those as possibilities before assuming CF has a "leak". Also, if you see use of CF heap as being "high" (using the CF Server Monitor, FusionReactor, SeeFusion, or similar tools), be sure to do a GC and see if that use of memory drops. If so, then the "high memory use" was nothing after all. Hope some of that's helpful.
Comment by External U.
20552 | August 22, 2013 10:33:39 PM GMT
In reply to carehart: - Variables that are not referenced should be garbage collected, if somehow they are still referenced that would constitute a memory leak in my opinion. Wether its within or across requests, this does not change the fact that its a leak. - There are use cases where you need to create a lot of objects, importing data for example. I do not like to leave OOP because coldfusion cannot handle it, but this always has been a problem for coldfusion which is one of its biggest drawbacks. But without this bug it is not a problem. - Using an object pool or flyweight design pattern for 1000's of objects, not 100.000's while coldfusion actually can handle 1000's of objects easily i find a strange bug workaround. - As java holds references in the dummycompmap variable ofcourse a GC does not help. Ive tried. regards
Comment by External U.
20553 | June 04, 2014 10:51:31 AM GMT