- Java Garbage Collection
- Objective-C Retain/Release
- etain Count
- The autorelease pool
- Conclusion
Objective-C Retain/Release
Whereas Java employs an automatic system to manage memory, Objective-C's system is almost completely manual. The system that Objective-C uses is called retain/release. The basic premise behind the system is that if you want to hold on to a reference to another object, you need to issue a retain on that object. When you no longer have a use for it, you release it. Similar to Java, each object has a retain count. When that count reaches zero, the object is released and the memory is recovered.
One primary difference, other than the manual nature of the memory management, is when the objects are released. Unlike Java, as soon as the object reaches a zero retain count it is released, which contrasts with Java's polling mechanism. The developer thus has more control over when objects are released and can avoid program stalls.
The code to retain and release objects in Objective-C is very straightforward. For example, the following code snippet retains an object:
- (void)setName:(NSString *)newName { [newName retain]; name = newName; }
In this example method, an NSString pointer is passed into the method. The example code calls retain on the NSString pointer and then changes the name pointer in the object to the new pointer. Those who are familiar with Objective-C will notice that this simple method has a potential memory leak. If the name variable was previously pointing to a different retained object, the reference to it is lost, but the object still thinks it is being retained and therefore will not be released. To solve this problem, the previous name pointer needs to be released prior to being reassigned to the new NSString pointer.
The updated method is as follows:
- (void)setName:(NSString *)newName { [newName retain]; [name release]; name = newName; }
The order of the retain and release in this implementation of the method is extremely important. It is possible that the method could be called passing in a reference to the object that is already being retained. If the release occurred prior to the retain, the object could potentially be removed from memory prior to the retain being called and then name would be pointing to a dead reference.
Another implementation of this method that is frequently used is as follows:
- (void)setName:(NSString *)newName { if (name == newName) return; [newName retain]; [name release]; name = newName; }
In this implementation, the two objects are compared prior to the retain release cycle, which has the added benefit of being slightly faster in the event that the method is called frequently. However, it has the disadvantage of being compared on every call, which would be wasteful if the two objects could never be the same.
Having explicit control over object retention gives the developer the benefit of having complete control over when memory is reclaimed and when objects are destroyed. With that greater control comes a greater responsibility to ensure that the application does not leak memory.