• Home
    • View
    • Login
    This page
    • Normal
    • Export PDF
    • Export Word
    • Attachments
    • Page Information

    Loading...
  1. Dashboard
  2. Port: MacOSX
  3. Main
  4. Mac OS X Port Development
  5. ObjC Memory Management and JNI

Page History

Versions Compared

Old Version 7

changes.mady.by.user Mike Swingler

Saved on Jun 09, 2011

compared with

New Version 8

changes.mady.by.user Mike Swingler

Saved on Sep 21, 2011

  • Previous Change: Difference between versions 6 and 7
  • Next Change: Difference between versions 8 and 9
  • View Page History

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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

  • 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
  • This keeps the number of JNI global refs HotSpot has to manage to a minimum
    • Java objects should not be pinned in the Java heap until some random native retain count lowers or the ObjC-GC decides to kick in
  • Java objects that own native objects have to concretely define the lifecycle of the native objects they hold
    • Do not let native objects hold onto Java objects in JNI global refs, or you can create a cycle across the Java and ObjC garbage collectors, and neither collector will realize that they can deallocate their respective objects

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
  • When the Java object is done with the native object, it must be explicitly "hard" CFRelease()'d
    • This balances the "hard" CFRetain() which occurred before it was passed up to Java
  • You need to determine if the object is safe to CFRelease() from any thread, or must only be done from the main AppKit thread
    • In some cases, releasing an object may do nothing but decrease it's retain count, but in other cases it will cause the object's -dealloc or -finalize method to be called, and those may not be any-thread safe if they end up releasing AppKit objects
  • The ObjC garbage collector cannot see into the Java heap, and infer if any native objects are still "alive"

Don't manage JNI global refs yourself

  • If you need to pass a Java object through native (like to the main AppKit thread, or inside of an NSArray), use JNFJObjectWrapper or JNFJObjectWeakWrapper
    • It handles all the details of managing a JNI global ref in a native ObjC object in both RR and GC modes
  • If you have a JNIEnv when you are done with the JNFJObjectWrapper, pre-clear the reference
    • It is more efficient than the wrapper's -dealloc, which may have to connect the current thread to the JVM (possibly a ObjC-GC collector thread), just for the purposes of deleting the ref.
Overview
Content Tools
ThemeBuilder

Terms of Use
• License: GPLv2
• Privacy • Trademarks • Contact Us

Powered by a free Atlassian Confluence Open Source Project License granted to https://www.atlassian.com/software/views/opensource-community-additional-license-offer. Evaluate Confluence today.

  • Kolekti ThemeBuilder Powered by Atlassian Confluence 8.5.23
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 225, "requestCorrelationId": "a0fa6c9b4839a444"}