Core Java APIs and the Java Runtime on OS X
This article discusses the differences between the Core Java APIs on OS X and other platforms. In general, the Core Java APIs behave as you would expect them to on other platforms, so most of them are not discussed in this article. There are a couple of details concerning Preferences that you should be aware of, as discussed in “Other Tools.”
OS X v10.3 and later supports IPv6 (Internet Protocol version 6). Because Java SE 6 uses IPv6 on platforms that support it, the default networking stack in OS X is the IPv6 stack. You can make Java use the IPv4 stack by setting the
java.net.preferIPv4Stack system property to
The Preferences API is fully supported in OS X, but there are two details you should be aware of to provide the best experience to users:
The preferences files generated by the Preferences API are named
com.apple.java.util.prefs. The user’s preferences file is stored in their home directory (
~/Library/Preferences/). The system preferences are stored in
/Library/Preferences/and are only persisted to disk if the user is an administrator.
To be consistent with the OS X user experience, your preferences should be available from the application menu. The
com.apple.eawt.Applicationclass provides a mechanism for doing this. See J2SE 5.0 Apple Extensions Reference for more information.
It is recommended that you use the Java JNI template in Xcode as a starting point for your JNI development. This template creates a bundled Mac app with a JNI library inside its Resources folder.
JNI libraries are named with the library name used in the
System.loadLibrary() method of your Java code, prefixed by
lib and suffixed with
.jnilib. For example,
System.loadLibrary("hello") loads the library named
libhello.jnilib. Java HotSpot also recognizes
.dylib as a valid JNI library format as of OS X v10.5.
To build as a dynamic shared library, use the
-dynamiclib flag. Since your
.h file produced by
jni.h, you need to make sure you include its source directory. Putting all of that together looks something like this:
cc -c -I/System/Library/Frameworks/JavaVM.framework/Headers sourceFile.c
cc -dynamiclib -o libhello.jnilib sourceFile.o
For example, if the files
hola.c contain the implementations of the native methods to be built into a dynamic shared JNI library that will be called with
System.loadLibrary("hello"), you would build the resultant library,
libhello.jnilib, with this code:
cc -c -I/System/Library/Frameworks/JavaVM.framework/Headers hola.c
cc -c -I/System/Library/Frameworks/JavaVM.framework/Headers hello.c
cc -dynamiclib -o libhello.jnilib hola.o hello.o -framework JavaVM
Often JNI libraries have interdependencies. For example assume the following:
libA.jnilibcontains a function
libB.jnilibneeds to link against
libA.jnilibto make use of
Such an interdependency is not a problem if you build your JNI libraries as dynamic shared libraries, but if you build them as bundles it does not work since symbols are private to a bundle. If you need to use bundles for backward compatibility, one solution is to put the common functions into a separate dynamic shared library and link that to the bundle. For example:
Compile the JNI library.
cc -g -I/System/Library/Frameworks/JavaVM.framework/Headers -c -o myJNILib.o myJNILib.c
Compile the file with the common functions.
cc -g -I/System/Library/Frameworks/JavaVM.framework/Headers -c -o CommonFunctions.o CommonFunctions.c
Build the object file for your common functions as a dynamic shared library.
cc -dynamiclib -o libCommonFunctions.dylib CommonFunctions.o
Build your JNI library as a bundle and link against the dynamic shared library with your common functions in it.
cc -bundle -lCommonFunctions -o libMyJNILib.jnilib myJNILib.o
A complete example of JNI development can be found in the MyFirstJNIProject sample code. More details on JNI can be found in Tech Note TN2147: JNI Development on OS X.
To interoperate with the Objective-C runtime from JNI, link against JavaNativeFoundation.framework, which is a sub-framework of JavaVM.framework. It contains Objective-C classes and macros to automatically set up and tear down autorelease pools, catch and re-throw Java and Cocoa exceptions, hold JNI global references in Foundation container classes, and convert object graphs of strings, numbers, lists, maps, and sets.
The Java Runtime
The Java implementation for OS X includes the Java HotSpot VM runtime and the Java HotSpot client and server VMs, all from Sun. The VM options available with the Java VM in OS X vary slightly from those available on other platforms. The available options are presented in Java Virtual Machine Option Reference for Mac.
When calling the
Runtime.exec() method, be sure to call
Runtime.exec(String cmdarray) or one of its counterparts, instead of the single-string version (
Runtime.exec(String command)). Passing a string outside of an array can have unpredictable results.
Runtime.exec(String cmdarray) behaves as it does in a standard Unix environment.
Virtual Machine Properties
“Note” lists the basic properties of the Java VM in OS X. You can use
System.getProperties().list(System.out) to obtain a complete list of system properties.