Search code examples
javagarbage-collectionaemsling

Why resourceResolver object should be closed


As stated here, I should close the resource resolver obtained from factory.

It is very important to call the close() method once the resource resolver is not used any more to ensure any system resources are properly clean up.

But I could not understand why should I do it because why java garbage collection framework does not release the memory automatically? I know an object will not be garbage collected if it has a reference. Lets take this example:

 public class MyServiceImpl{

  @Reference
  ResourceResolverFactory rrf;

  public void someFunction(){
      ResourceResolver resourceResolver = rrf.getServiceResourceResolver(Map object);
      resourceResolver.getResource(path);
   }

 }

In the above piece of code, resourceResolver object is used to just to get the resource. And after the end of function execution there is no more reference present for resourceResolver object. So I do not understand why memory cannot be free by the java garbage collector? What reference it still holds?

One reason I can think of, as I know the ResourceResolverFactory class gives Singleton object and in case of Singleton class the object is not eligible for garbage collection until the program ends and during this time if we create thousands of ResourceResolver objects then memory will not free until program ends. Is this a valid reason ? Is there any memory mapping between Singleton ResourceResolverFactory and ResourceResolver object?


Solution

  • The ResourceResolver interface abstracts away the details of accessing resources across multiple sources. Depending on the underlying implementation, this could be the JCR, a bundle resource or some other form of storage. Access to the underlying "database" may require some form of authentication. For example, typically, when reading resources from the repository in AEM, there's an underlying JCR session open for each Resource Resolver. This session needs to be terminated when it's no longer needed. Broadly speaking, there's more to it than pure garbage collection/memory management constraints and, depending on the underlying implementation, there may be some other resource cleanup involved. The Javadoc on ResourceProvider explains this in a little more detail.

    That said, this behavior is achieved with a number of interfaces and their corresponding implementation classes that introduce a few interesting things with a bearing on the garbage collection process.

    TheCommonResourceResolverFactoryImpl class, which implements the shared functionality of all resource resolver factories (see ResourceResolverFactory) is a Singleton that holds a map of weak references to open ResourceResolver instances.

    This needs to be cleaned up as a particular ResourceResolver instance is closed.

    You may notice that there's a ResourceResolverControl associated with each of those ResourceResolver instances. It is the ResourceResolverControl class that ensures all ResourceProvider instances are properly closed together with the encompassing ResourceResolver. As you close a particular ResourceResolver, this is orchestrated by the relevant ResourceResolverFactory

    The way I understand it, the relationships between those classes and their garbage collection implications aren't the reason we have to call ResourceResolver#close. The design reflects the need to abstract away the different providers, some of which use resources calling for a cleanup.