The Cocoa runtime uses two modes of managing object allocation and de-allocation:
- Retain/Release (RR)
- Garbage Collection (GC)
Developers who create libraries that can be used in other applications (like Java) need to be aware and write Objective-C code that works in both modes. When Java's garbage collector is added into the mix with JNI local refs, global refs, and passing native objects up to Java as jlongs, memory management can get quite complicated!
There are a few simple rules to follow when writing JNI code that handles Cocoa objects:
Always use JNF_COCOA_ENTER()/JNF_COCOA_EXIT()
- These macros ensure that an autorelease pool is always setup and popped so ObjC objects are not leaked in RR mode.
- They also catch ObjC exceptions that are thrown, and rethrow them as Java exceptions
As a rule, Java objects should own native objects in jlongs
- This keeps the number of JNI global refs HotSpot has to manage to a minimum
- Java objects are not pinned until some retain count lowers or the ObjC-GC runs
- Java objects that own native objects have to concretely define the lifecycle of the native objects they hold
- The jlong type is used because it is big enough to hold both 32 and 64-bit sized pointers
- Use the jlong_to_ptr() and ptr_to_jlong() macros to correctly handle casting and avoid sign-extension problems
Native objects held by Java objects must have a "hard" CF-retain count of 1 before being passed up to Java
- ObjC objects that are +alloc'd or -retained are not actually pinned in GC-mode unless they have been CFRetain()'d
- As a counterpoint, any CFRetain()'d ObjC object must be -released or -autoreleased for it's retain count to remain balanced in RR mode
- The ObjC garbage collector cannot see into the Java heap, and infer if any native objects are still "alive"
Overview
Content Tools
ThemeBuilder