If you are familiar with "C" programming language, you would know that, it is the responsibility of the application to release the memory (Dynamically allocated memory) back to the system at the end of its execution. "C" language uses "malloc" for memory allocation and "free" function to release the memory gracefully. If the memory used up by the application is not released, it leads to memory leaks and eventually the application will run out of memory. This concept of releasing/deallocating the memory back to the system is called Garbage collection.
All the Java objects are created by using the "new" operator. The memory for this objects is allocated in "heap", in general all the dynamically allocated memory would be in the Heap. The local variables are stored in "stack", the memory used by the local variables is freed automatically after its scope is lost. If you are not familiar with Stack/heap or how the memory management working in a system, please take a look at the memory management section of our C module. The concepts of stack, heap, local variables, memory management works the same, in all the programming languages (Except for few exceptions here and there).
In Java, as we know all the objects that are created using the "new" operator are stored in the heap. If you are wondering what happens to the objects that are instantiated with in method, will they be treated as local variables? The answer is No. It does not matter where the object is created, it is always stored in Heap. So, for the objects created inside a method, the actual memory is allocated in the heap and the reference to that memory is stored in the stack.
Java run time system takes care of deallocating the memory and the approach it takes to do so depends on the system. In general unlike C programming language, the application does not have to worry about "freeing the memory/memory leaks" as Java runtime systems takes care of it.
Java runtime system will not be able to free a non-java resource, as a part of garbage collection concept. File descriptors, sockets etc are some of the examples of non-java resources. Application will have to take up that responsibility with the help "finalize" method.
Application has to define a method "protected void finalize()" and the logic to free up the non-java resources will be in this method. Java run time system invokes this method just before the garbage collector kicks in to free up the memory. Since the Java application do not know when the garbage collector kicks in, it is always better to have a backup plan (not to depend on finalize all the time) and to release the non-java resources gracefully.