To explain the problem, first we need to look at some key issues with a URLClassLoader. URLClassLoaders are notorious for causing memory leaks, because, for them to be garbage collected, all instances to themselves and the classes that they have created need to be garbage collectible.
This means that if you access a class from a URLClassLoader and hold it somewhere in memory, then the URLClassLoader can never be garbage collected.
This is exactly what happens with ColdFusion.
When ColdFusion does some introspection and resolution of ColdFusion code against a Java object, somewhere, deep inside its hidden internals, it keeps a strong reference to the Class object that refers to that Java object. This means that when the JVM comes along to garbage collect the instance of the URLClassLoader, it can't do it, because ColdFusion has a reference to a class that it loaded somewhere inside.
So, the memory leak only ever actually happens when an instance of a URLClassLoader is no longer available to ColdFusion, as it is never then garbage collected by the JVM.
How does this translate to using JavaLoader? Well, a perfect example of this is where you put an instance of JavaLoader in the application scope, because generally it is used as a singleton. JavaLoader (and anything that subsequently uses JavaLoader) has an instance of a URLClassLoader inside it. However, when the application scope times out, the JavaLoader CFC may well be garbage collected, but the URLClassLoader isn't, which can cause a memory leak.
To note however, in production systems the leak is minimised in situations like this, as it is often very rare that the application scope will ever time out.
So what is the workaround for this issue? To note, I have been pushing at Adobe to get a hotfix out for CFMX to resolve this issue, but we can definitely still use this technique now, without having to worry about memory leaks.
Essentially, the memory leak only happens when the URLClassLoader is no longer available to CF, i.e. an application scope times out, or something similar - so we just need to make sure that it never, ever, times out. How can we do that? why, put it in the Server scope of course!
Since variables in the Server scope never time out, we don't need to worry about the URLClassLoader (or JavaLoader) being lost and then recreated, as it always exists. As long as you put it in the Server scope under a key no one will ever need to utilise (I like a hard coded UUID myself)! Hence we beat the memory leak monster!
I have just committed a fix for Transfer that automatically puts the JavaLoader it uses into the Server scope, so even if your TransferFactory times out, the JavaLoader never will, which means there is no leak, and the RC2 for 0.6.3 will have this as well.
Hopefully Adobe will put out a hotfix for this issue, but until then, put your JavaLoaders in the Server scope.