PATH Documentation > Release Notes

Mac OS X 10.1.1 Release Notes:
Java

Mac OS X bundles Sun’s Java 2 Standard Edition (J2SE). This version is based on the Solaris Java Development Kit (JDK) version 1.3.1, including the client version of HotSpot 1.3.1.

This version may be discussed in public forums like Apple’s java-dev mailing list (preferred) or the comp.lang.java newsgroups.

For more technical information about Java on Mac OS X, see Java Developer Documentation.


Topics


What's New in Mac OS X 10.1.1

The Mac OS X 10.1.1 update addresses an Apple-specific issue in HotSpot with implicit or explicit use of java.lang.String.intern() and System.identityHashCode().

You can verify that this update has been applied by looking at the os.version system property (see System Properties).


Known issues with upgrade installation

If you install Mac OS X 10.1 over any version of Mac OS X 10.0, you should be aware of two limitations of the installer, and the steps you can take to work around them.

Java extensions not preserved

Preferred locations for installing Java extensions have changed. See Java extension locations for more details.

Doing an update install with the User CD will not preserve any files which you may have installed in $JAVA_HOME/lib/ext (/System/Library/Frameworks/JavaVM.framework/Versions/1.3/Home/lib/ext). Before you install, you should move these extensions to a safe place, and later reinstall them in the Local domain. If you did not save your extensions prior to installing, you will have to reinstall them from your original source disks or downloads. Be careful when reinstalling extensions that you do not inadvertently reinstall older versions of extensions which Apple has provided as part of Java on Mac OS X 10.1.

MRJAppBuilder is not upgraded

The Developer CD update installer does not update MRJAppBuilder. To assure that MRJAppBuilder is properly installed, you should remove MRJAppBuilder from /Developer/Applications before running the installer on the Developer CD. If you have already run the installer, you can check the version of MRJAppBuilder to determine whether the correct version has been installed. The correct MRJAppBuilder version is 1.1. The older version of MRJAppBuilder was 10.0. If you still have the older version of MRJAppBuilder, remove it and then rerun the Installer on the Developer CD, selecting only the Developer Tools Software package.


Java Virtual Machine

Mac OS X ships with the client version of the HotSpot virtual machine from the JDK 1.3.1 technology train.

Some options available in prior VMs (e.g. JITC settings) are not applicable to the HotSpot VM. In addition, HotSpot VM options are in the "non-standard" group that are of the form -Xoptionname. For a list of these options, type java -X in a Terminal window.

The HotSpot VM’s memory performance is excellent and its compilation performance is very good in real-world applications, but the engine has not been tuned for micro-benchmarks such as CaffeineMark.

Java threads are mapped directly to native Mach threads and are therefore fully preemptive, even (unlike MRJ on Mac OS 9) with regard to the host application and other applications. Java thread priorities are mapped to native thread priorities such that higher priority threads will get preferentially scheduled. You should not, however, rely on any particular scheduling behavior other than that.

System Properties

Some notable Java system properties include:

Name

Value

Comments

os.name

Mac OS X

This value was "Darwin" in early pre-releases of Mac OS X, and "Mac OS" in MRJ on Mac OS 9. It is suggested that you use System.getProperty("os.name").startsWith("Mac OS") if you need to test whether your code is running on any version of Mac OS.

os.version

10.1.1

This was "1.1" (the version number of the Darwin kernel) in early pre-releases of Mac OS X.

mrj.version

3.1

Testing for the existence of this property is the general way to detect whether you are using an Apple-developed JVM, although to detect specific features like JDirect or MRJToolkit it is better to use reflection to check for the existence of the specific classes they use.

line.separator

'\n'

This differs from MRJ on Mac OS 9, which used '\r', but is consistent with Unix-based Java implementations and with the BSD and Cocoa frameworks.

Locales and default locale

Java on Mac OS X sets a default locale based on the choice in System Preferences -> International: French maps to fr_FR, English to en_US, Japanese to ja_JP, French Canadian to fr_CA, etc.

In order to get a locale and language combination not supported by System Preferences, such as French language in the U.S. (fr_US), the default locale can be overridden by the following settings before the Java VM starts up. The options listed first override the later ones.

  1. The Java properties user.language and user.region, defined on the java command line, or in MRJAppBuilder property settings
  2. The value of the LC_ALL environment variable, set to one of the ISO standard language (optionally plus region) codes. LC_ALL is mapped to locale using a set of default rules derived from the language codes outlined in ISO 639 and the country codes outlined in ISO 3166, such as en -> en_US, fr -> fr_FR, ja -> ja_JP, etc. See www.unicode.org for more details on these ISO specifications.
  3. The International settings in System Preferences (as mentioned above)
  4. The value of the LANG environment variable

Specifying a locale within Java code using Locale.setDefault(newLocale) can be done after the VM is running, and overrides all other options.


Debugging

Project Builder

Java debugging is now fully operational in Project Builder, and is the recommended way to debug your Java applications.

jdb

jdb, the command-line Java debugger, works with the HotSpot Java Virtual Machine. To debug your code with jdb, do:

	$ jdb nameofjavaclass arguments

See the jdb man page for more details.

gdb

Currently, "/usr/bin/java" is a script. Because gdb won’t recognize the script as an executable format, you can’t simply type "gdb java" to debug your native code. To debug using gdb, you must type the full path to the java executable, like this:

$ gdb /System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Commands/java

Once gdb starts, you may establish a different CLASSPATH for loading java code from within gdb:

(gdb) set environment CLASSPATH foo:bar
(gdb) run nameofjavaclass arguments

The ps() and pss() gdb utility functions that were described in previous releases are no longer recommended for displaying stack trace information.

To display Java stack traces, use one of these methods:

Note that if you deliver a signal to a process that is running in gdb, gdb will break on the signal. You can just continue on (with the command "c") as you are actually not interested in the signal itself, but in the output the signal handler gives you.

You can have monitor status included in the the stack trace information. There are several ways to enable this option (this applies also to all other -XX: based VM options):

If you are reporting a bug that results in a crash or a deadlock, please include the Java stack trace information as described above. In the case of a crash, please include the native stack trace as well. To get a native stack trace, reproduce the bug while running in gdb, and run the bt command after the crash. To get all native backtraces, use the gdb command "thread apply all bt".

See the gdb man page for more details.


Tuning the Heap Size

The default heap size on Mac OS X is 64MB. Since the Mac OS X Java HotSpot VM uses generational garbage collection, more memory is actually reserved to accommodate the various generations.

For applications which allocate large numbers of objects/data, you may want to increase the heap size. This may have an effect on overall performance, either positively or negatively, so if you decide to do this, you should test your application under various different scenarios with different heap sizes. Generally speaking, a larger heap will result in fewer garbage collections, but those will take longer. You can study this effect by invoking the java command line program with the -verbose:gc flag. This will give you a measure of how long each garbage collection is taking.

There is a limitation in the Java VM as shipped in 10.0 and 10.1 that the heap maximum cannot be made larger than 590MB. If the heap is larger, the java command line program will crash. This will be fixed in an upcoming release. If you do need a larger heap, you can turn off the shared classes support in our Java VM passing the -XX:-UseSharedGen flag to HotSpot. This will allow a maximum heap size of up to about 986MB.


Profiling tools

Java on Mac OS X provides hprof as a basic profiling tool. The reliability of data provided by hprof is better than in previous releases, though some features are still not thoroughly tested.

The HotSpot Java VM includes the -Xprof option which provides basic flat CPU usage on a per-thread basis, which we have found useful.

See Java Development Tools for more information about other tools.


Building Java Native Interface (JNI) libraries

In Mac OS X, native methods that are implemented using the Java Native Interface are built into JNI libraries. Only the application that dynamically loads a JNI library has access to it. JNI libraries must be mach-o. CFM libraries are not supported. See TechNote 2003: Moving Your Code to Mac OS X, and the Mac OS X Technology Overview book for more details on mach-o and CFM.

JNI libraries are always named libname.jnilib, where name is the value of the string used in the call to System.loadLibrary(). For example, to load the library named libhello.jnilib, you would make the following call in your Java code:

System.loadLibrary("hello");

To build a JNI library, execute the following command:

$ cc -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers -o libname.jnilib -framework JavaVM sourceFiles

For example, if the files hello.c and goodbye.c contain the implementations of the native methods to be built into libhello.jnilib, you would build libhello.jnilib with the following command:

$ cc -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers -o libhello.jnilib -framework JavaVM hello.c goodbye.c

A common problem for JNI developers is that JNI dynamic libraries have interdependencies. For example: libA.jnilib contains a function foo(). libB.jnilib needs to link against libA.jnilib to make use of foo(). This will not work on Mac OS X because JNI libraries are bundles (all symbols are private to a bundle). One solution to this dependency problem is to put the common functions into a separate dynamic library (libC.dylib in this example) and link both libA.jnilib and libB.jnilib to libC.dylib.


Building native applications that launch the Java VM

To build a C application that starts a Java VM session, you must link with the JavaVM framework; e.g.

$ cc myapp.c -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM -o myapp


AWT and other class libraries

Windows and Dialogs

Window titles, controls, menu titles and menu items can use any Unicode characters supported by Mac OS X. (In MRJ on Mac OS 9, characters of different non-Roman writing systems, e.g. Kanji and Arabic, couldn’t be mixed in a single title.)

Window coordinates and insets are compatible with the JDK. In a nutshell: Window bounds refer to the outside of the window’s frame, and the coordinates of the window put (0,0) at the top left of the title bar (not at the top left of the content region as in MRJ on Mac OS 9). The getInsets method returns the amount by which content needs to be inset in the Window to avoid the window border. This should only affect applications that are doing precision positioning of windows (especially full-screen windows), or those that bypass LayoutManagers to do their own hardcoded component positioning.

Windows in Mac OS X are double-buffered. Java on Mac OS X attempts to flush the buffer to the screen often enough to have good drawing behavior without compromising performance. If for some reason you need to force window buffers to be flushed immediately, just call Toolkit.sync().

Java processes that are launched from a shell will not show up in the Dock or the floating Application List until/unless they show a window. In the Dock, these processes will then show up as items with a default Java icon. This allows server-type processes to run behind the scenes with no user visible manifestation. In contrast, any app built with MRJAppBuilder will always be user visible, and have the icon you have selected for it.

Live window resizing is off by default. To enable live window resize, see the section on GUI customization.

Graphics and Java2D

Our Graphics/Java2D implementation is based on Apple’s Quartz graphics engine. Java2D and Quartz have very similar feature sets, inherited largely from PostScript. Java on Mac OS X uses Quartz for all graphics&emdash;as opposed to the JDK, which drops down to GDI or X-Windows for simple 1.1-style drawing&emdash;and while Quartz is very fast at complex rendering, it has not yet been optimized for some basic shapes like diagonal lines.

Anti-aliasing is on by default for text and graphics, but can be turned off using the properties described in the section on GUI customization, or by calling setRenderingHint() within your Java application.

To enable experimental code that uses hardware acceleration for graphics where possible, see the section on GUI customization.

Compatibility issues to note:

Swing

Mac OS look-and-feel

There is a new Mac OS look-and-feel which uses the Appearance Manager to do its rendering, giving it full support for the Mac OS X Aqua interface. This is the default look-and-feel, and is set as such in the swing.properties file. Most Swing-based applications have preference settings that allow you to switch the look-and-feel.

Things to note about the Mac OS look-and-feel:

Known bugs:

Bundle traversal in JFileChooser

To allow developers more flexibility in dealing with Mac appBundles and packages, we’ve added properties to the Mac FileChooser:

Possible values for these properties are "always", "never". They can be applied globally by setting them with UIManager.put and per-instance with fileChooser.putClientProperty. They’re set to "always" by default.

The Aqua JFileChooser also supports alias traversal, but this only works with the default FileView, so if you replace it (as FileChooserDemo does), aliases will not be traversable, because Unix sees aliases as files.

Event handling

Known problems with event handling:

GUI customization

There are many system properties that can be set (via a .properties file in your home directory, via MRJAppBuilder, via Project Builder, or on the java command line) to customize various aspects of the GUI:

Property

Default

Function

com.apple.macosx.AntiAliasedTextOn

true

Use anti-aliasing when rendering text.

com.apple.macosx.AntiAliasedGraphicsOn

true

Use anti-aliasing when rendering graphics.

com.apple.macos.useScreenMenuBar

false

Puts Swing menus in the Mac OS menu bar, if using the Aqua look and feel.

com.apple.hwaccel

false

Uses hardware acceleration for graphics if possible. This improves drawing speed dramatically in many cases, but is a pre-release implementation.

com.apple.mrj.application.growbox.intrudes

true

Resizable window’s grow-box intrudes into AWT content (if turned off, bottom of window is pushed down 15 pixels.)

com.apple.mrj.application.live-resize

false

Enables live resizing of windows.

com.apple.mrj.application.apple.menu.about.name

none

If defined, an "About" command will be added to the top of the application menu, and can be detected by registering a com.apple.mrj.AboutHandler.

com.apple.macos.use-file-dialog-packages

none

If defined, and set to true, causes java.awt.FileDialog to select application packages as if they were files, and will not allow navigation into them.

The properties that apply to windows can be changed at runtime, but the changes apply only to windows that do not yet have peers (those that have not yet been shown or packed).

Giving applets permission to access internal properties

Unsigned applets can’t access the above properties. The one current exception is com.apple.macos.useScreenMenuBar. If you need to use other internal properties from an applet, you can grant permission to access them by adding a line like the following to your system-wide policy file, which is located at ${JAVA_HOME}/lib/security/java.policy:

java.util.PropertyPermission "internal.property.goes.here", "read,write";

RMI and paths that contain spaces

If there are spaces in the path containing a Java class, RMI may not work correctly. This problem occurs with Java on other platforms, but paths containing spaces are more common on Mac OS.

Changes to java.awt.FileDialog

Any AWT FileDialog can now be resized by the user.

Non-Roman file and directory names are now properly handled.

Calling setDirectory() on a FileDialog before it is shown will now set the initial location. Using setFile() still has no effect because the underlying Navigation Services implementation does not support initial file selection.

Application packages are no longer grayed out in a FileDialog. If the System property "com.apple.macos.use-file-dialog-packages" is "true", then they can be selected and returned; otherwise you can navigate inside the application package directory, but not return the directory itself. Note: Since application packages are directories, the java application that sets this property must be able to handle a directory being returned by FileDialog.

When using directory picker mode of FileDialog (setMode(3)), the way the selected directory is returned has changed. In Mac OS X 10.0, getDirectory() returned the full path, and getFile() always returned null. In Mac OS X 10.1, getDirectory() returns the full path to the parent of the selected directory, and getFile() returns the selected directory name, or null if the user cancelled the dialog. Therefore, your directory picker code can be the same as for files: check getFile() for null to see if user cancelled; then use newFile(fd.getDirectory(), fd.getFile()).

Sound

Java on Mac OS X supports sound output. However, audio input is not currently supported.


Other APIs

JDirect

Mac OS X implements JDirect3, which allows access to pre-existing native code libraries from Java. JDirect2 code will require minor modifications to run under JDirect3. JDirect1, which has been deprecated since 1997, is no longer supported.

The JDirect sample code supplied in source form in the MRJ 2.2 SDK will not work on OS X. That code is not Carbonized and it does not use JDirect3.

Read Compatibility between JDirect 2 and JDirect 3 for more information on how to convert JDirect2 code to use JDirect3 on Mac OS X.

Toolbox synchronization

It is imperative that you synchronize all Toolbox calls. Java threads are native Mach threads and can preempt Toolbox calls made by the host app or by other Java threads. Carbon is not yet reentrant or thread-safe, and reentrant calls can corrupt memory or crash the app, so it’s imperative that only one thread be inside Carbon at any time.

The correct method for Toolbox synchronization has changed since Public Beta. Java on Mac OS X no longer supports the synchronization method (Toolbox.LOCK) described in the 10.0 Public Beta Java release notes. The correct way to call the Toolbox (aka Carbon) from Java on Mac OS X is:

import com.apple.mrj.macos.carbon.CarbonLock;
   
try {
    CarbonLock.acquire();
   
    <Carbon call here>
   
} finally {
    CarbonLock.release();
}

This way the CarbonLock handling can easily be reversed for JDirect callbacks.

Be sure to use CarbonLock around all Carbon calls. Since threads are preemptive on Mac OS X, one should hold the CarbonLock for the very least amount of time possible. Deadlocks occur more often when the CarbonLock is held too long.

Also, don’t do anything which may throw exceptions in the finally block that calls CarbonLock.release(). Structure your code so that the CarbonLocking is separate from other finally blocks.

Debugging features for JDirect

To help debug JDirect on Mac OS X, if you define a shell variable named JDIRECT_VERBOSE, JDirect will write verbose loading info to stderr. Note that this only works when launching java code from the command line&emdash;not when double-clicking the bundled application in the Finder. But you can launch any double-clickable application from the command line by specifying the path to the application’s executable.

For example, to set the shell variable, and then launch an application called Foo.app, you would do the following in csh:

% setenv JDIRECT_VERBOSE
% /path/Foo.app/Contents/MacOS/Foo

MethodClosureUPP not supported

The class MethodClosureUPP was created for use on Mac OS 9 and is not supported on Mac OS X (the design of that class assumes the existence of MixedMode). If you are using Toolbox callbacks and want code that will run on Mac OS 9 or Mac OS X, you will need to have a helper class that creates a new MethodClosureUPP when on Mac OS 9 or a new MethodClosure when on Mac OS X.

JDirect implies user interface

For this release of Mac OS X, any use of JDirect will cause Carbon to be initialized, a Dock entry added, and a menu bar installed. This was necessary because Carbon is not thread safe and must be initialized from the correct thread. A future release of JDirect will provide a way to specify which JDirect native calls do not load Carbon, and thus are safe to run without initializing Carbon.

JDirect access to bundles

Normally, your JDirect_MacOSX String is a full path to a dylib which is the standard packaging for shared mach-o code on Mac OS X. But you can also specify a full path to a CFBundle. The CFBundle path name must end in ".bundle" and be a properly constructed directory. The CFBundle supports both mach-o code and CFM code. See the Bundle Services Documentation for more details.


Java Embedding API (formerly JManager)

New functionality in Mac OS X has enabled us to replace JManager (the embedding technology for MRJ on Mac OS 9) with a Carbon-based Java Embedding API. JManager is not supported in Mac OS X.

The Java Embedding API is contained in the JavaEmbedding framework (/System/Library/Frameworks/JavaEmbedding.framework). There are three header files: JavaApplet.h, JavaControl.h, and JavaEmbedding.h.

The new Java Embedding API is smaller and simpler than JManager. The functionality previously supplied by JManager is available through the JNI Invocation API, the CoreFoundation API, or is unnecessary and has been removed. The functions that remain in the new Java Embedding API are primarily applet embedding and utility functions.

Native applications that want to invoke Java should launch a Java VM using the standard JNI Invocation API, and be sure to make the first call into the JavaEmbedding framework on the main thread.

Only native applications that want to embed a Java applet into their own windows need to use the new Java Embedding control creation APIs in <JavaVM/JavaControl.h>. These create a "Java Control"&emdash;a standard Control Manager control that contains a Java applet. The control creation APIs take a native Carbon WindowRef that references the window into which the Java Control is to be embedded. Most of the interaction with the control is through the calls in JavaControl.h.


MRJToolkit

The MRJToolkit utility routines from MRJ on Mac OS 9 are present in this release, but there are differences.

Some routines not implemented

Several of the MRJToolkit routines do not work: openURL(), setDefaultFileCreator(), and setDefaultFileType(). In a future release, openURL() may be implemented, but the other two will be removed entirely.

Handlers in command line applications

The MRJThingHandler interfaces (MRJAboutHandler, MRJCoercionHandler, MRJOpenDocumentHandler, MRJPrintDocumentHandler, MRJQuitHandler) will not work until the AWT is initialized. For packaged double-clickable applications, the AWT is initialized before your application’s main() is called. If you launch your java application from the command line, you must either register your handlers after your code has initialized the AWT, or force the AWT to be initialized via a simple snippet such as:

new Frame().pack();

MRJQuitHandler and default Quit menu item behavior

Every Java application with UI automatically gets an Apple menu and an application menu. The application menu follows the standard Aqua guidelines and contains a Quit menu item. By default, that Quit menu item will call System.exit(). If you have your own Quit (or Exit) item in your own menu, then when running on Mac OS X, you should change your menu to remove the Quit item. You can install an MRJQuitHandler, which will be called when the user chooses the Quit menu item in the application menu.

Known problems with MRJQuitHandler:


Developing, packaging, and launching Java

Jar files can now be launched directly from the Finder

If a jar file has a manifest that specifies the main class, it can be launched directly from the Finder by double-clicking it.

Java extension locations

Java can be extended by adding custom jar, zip, and class files, as well as native JNI libraries, in the location specified by the java.ext.dir property. In Mac OS X 10.0, this property pointed to /System/Library/Frameworks/JavaVM.framework/Versions/1.3/Home/lib/ext, and many third party applications placed their extensions there. There are two problems with this scheme: installing files in the System domain requires administrative privileges; and the extensions are tied to a specific version of the JDK.

In Mac OS X 10.1, java.ext.dir has been changed to contain a list of directories, and several additional locations for saving extensions have been added. This new scheme makes it possible to override extensions, and provides distinct locations for third party extensions, Apple extensions, and Sun JDK extensions. By default, Java searches for extensions, in order, in the following directories:

  1. User’s home directory (~/Library/Java/Extensions/)
  2. Local domain (/Library/Java/Extensions/)
  3. Network domain (/Network/Library/Java/Extensions/)
  4. System domain (/System/Library/Java/Extensions/)
  5. $JAVA_HOME (/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home/lib/ext/)

In general, third party developers should install extensions in the Local domain. Apple extensions, such as QTJava.zip, are installed in the System domain, and Sun JDK extensions are installed in $JAVA_HOME.

Project Builder for integrated Java development

Project Builder is a complete development environment that supports editing, compiling, packaging, running, and debugging Java applications, using the Java runtime on Mac OS X. See the Project Builder Documentation for more information.

MRJAppBuilder

MRJAppBuilder is a utility for packaging already-compiled Java applications to run on Mac OS X. MRJAppBuilder constructs applications in the new Carbon application bundle format. In order to package your application, you must specify (at a minimum) the main class name and the location of the output file. If you are not merging your Java class or jar files into the output, you will need to add them to the classpath. Each of these values can be set from within the Application panel.

The main class field is where you must enter the name of the class that contains main(). This field represents the value of the property com.apple.mrj.application.main. Remember to include any package information, such as com.foo.myclass. You can also press the "Choose..." button to choose a jar file that contains the main class.

The classpath field allows you to modify the classpath. Usually, this will be automatically set to point to the jar file that you’re bundling into your application. In the case where you wish to use a jar file that remains outside the application bundle, you need to add a classpath entry of the form:

$APP_PACKAGE/../MyJarFile.jar

$APP_PACKAGE is a special path string that represents the application bundle directory.

The last required field is the output file field. You must specify the name and location of the output file. You may either enter the path in the text field provided, or you may press the "Set..." button to set the location of the output file using the file chooser dialog.

You can add a custom icon to your application. Click on the icon in the Output file section to bring up a file chooser dialog for selecting an icns file.

Using the other tabbed panels is optional. The Mac OS X panel allows you to set values specific to the Mac OS X application bundle format. If you do not specify the CFBundleExecutable or CFBundleName, they will be set based on the name of the output file you choose.

The Java Properties panel allows you to set Java runtime properties. The main and classpath fields are not editable&emdash;they can only be set in the Application panel. The remaining properties are the standard properties supported by Java on Mac OS along with their default values. To set additional properties not listed in the table, simply add them to the end of the list. In previous versions of MRJAppBuilder, you were required to create a configuration file defining the Java runtime properties. This panel is a replacement for the configuration file.

The Merge Files panel provides a means for adding files to the application, such as zips or jars. Choose the "Add..." button to add files to the list. Each item added to the merge list will be copied into the application’s Contents/Resources/Java/ directory. Each item you add to the merge list gets automatically added to the classpath.

Console output from applications

Console output from packaged Java applications built by MRJAppBuilder, or from applets running inside Applet Launcher, appears in the system console, which can be viewed by launching /Applications/Utilities/Console.

If you want application output to appear in a Terminal window, you’ll have to launch the application from that Terminal. You can either use a "java" command directly with your jar or class files, as described in Launching java from the command line below, or launch the packaged application from the Terminal by specifying the path to the executable. Assuming the current directory is the parent directory of the application, you launch a packaged application like this:

MyJavaApp.app/Contents/MacOS/MyJavaApp

There are magic strings for IO redirection: $CONSOLE causes output to be displayed in a Java console window. $SYSTEM leaves stderr and stdout as is (directed to Console for double-clickable applications, or directed to the parent shell for applications launched from the command line).

Setting the Java working directory

When you build your application with MRJAppBuilder or Project Builder, the current Java working directory defaults to the parent directory of the application bundle directory. For example, if you’ve built an application named myApp.app inside the folder /Volumes/HD/myJavaApplications/, then the current directory would be /Volumes/HD/myJavaApplications/. Note that this is a change in behavior from pre-release versions of Mac OS X 10.0.

You can override the current Java working directory by setting the property com.apple.mrj.application.workingdirectory. This property must be an absolute path, or must start with $APP_PACKAGE, which is a special path string that represents the application bundle directory. Therefore, in this example, these are equivalent current working directory specifications:

com.apple.mrj.application.workingdirectory = $APP_PACKAGE/Contents/Resources/Java

com.apple.mrj.application.workingdirectory = /Volumes/HD/myJavaApplications/myApp.app/Contents/Resources/Java

Example of creating an application

Let’s assume you have a simple Java program, such as HelloWorld. Use javac and jar in the Terminal (in /Applications/Utilities/) to compile the source and create a jar file named HelloWorld.jar. Launch MRJAppBuilder from /Developer/Applications/. The active panel will be the Application panel.

Step 1: Set the Main classname

Click on the "Choose..." button and navigate to and select the HelloWorld.jar file. Click on "Select". In the "Choose Main Class" dialog, you should see only the name HelloWorld, since there is only one class containing a main() method. Click "OK". The main classname field should be automatically filled out and the classpath updated with the item Contents/Resources/Java/HelloWorld.jar.

Step 2: Set the Output file

Click on the "Set..." button and navigate to the desired output directory. In the "Select" dialog, type the name of the output file in the "Name" field. If you don’t enter one, the default will be the name of the folder you last clicked on. Click on "Select". The Output file field should be filled out with the full path to the output file. If you don’t append a ".app" extension to the name of your application, MRJAppBuilder will add the extension when it builds the application.

Step 3: Build the application

Click on "Build Application". That’s it! Your application can now be launched from the Finder. The HelloWorld.jar file was copied into the application, so you can move the application to any location and it will run.

Notes on the example:
  • All of the text fields in the Application panel are editable, so instead of using the dialogs, you could type the values for each field directly.
  • For more complex applications that have more than one jar file, use the Merge Files panel to add those files to your application.
  • We recommend that you add jar files to your application as opposed to individual class files.

Known problems with MRJAppBuilder:

Configuring packaged Java applications

A java application can be packaged as a double-clickable Mac OS X application via two methods:

There are two ways to specify Java configuration information in a packaged Java application.

Either way will launch properly on Mac OS X 10.0 and 10.1, but the MRJApp.properties way is deprecated. In the 10.1 Developer release, the ProjectBuilder templates have been updated to use the Info.plist while MRJAppBuilder still generates MRJApp.properties based files. A future release of MRJAppBuilder will create Info.plist based applications.

The Info.plist system will allow your application to run on both Mac OS X 10.0 and 10.1 as long as you build your application with the tools on Mac OS X 10.1. The stub of executable code inserted in a packaged application by MRJAppBuilder and by ProjectBuilder on Mac OS X 10.1 will first check for a key named "Java" in the Info.plist and if it exists, launch using the Info.plist mechanism. Otherwise, it uses the MRJApp.properties file. The executable stub inserted in a packaged application by MRJAppBuilder and by ProjectBuilder on Mac OS X 10.0 will only use MRJApp.properties.

Java key/values in Info.plist

An application Info.plist is an XML document containing static application information such as icons and version (see Mac OS X Technology Overview for more details).

All Java configuration information is stored in a sub-dictionary of the main Info.plist dictionary. The sub-dictionary has the key Java. For example:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="0.9">
    <dict>
        <key>CFBundleExecutable</key> 
            <string>JavaApplicationStub</string>
        ...
        <key>Java</key> 
            <dict>
                <key>ClassPath</key> 
                    <string>$JAVAROOT/SurfWriter.jar</string>
                <key>MainClass</key> 
                    <string>com.apple.SurfWriter</string>
            </dict>
    </dict>
</plist>

The following is a table of valid key/values that can be used in the Java dictionary:

Key

Value Type

Value

Comments

Jar

string

jar file path

Same as the -jar option to the java command line tool. It assumes the jar manifest contains the main class. The VM is started with the jar file as the only classpath entry. This option is used instead of the ClassPath and MainClass keys.

MainClass

string

fully qualified class name

Name of class whose public static void main(String[]) should be run. If the class is in a package, it you must specify the dot-separated full class name (e.g. com.apple.SurfWriter).

ClassPath

array of strings

classpath entries

Same as the -classpath option to the java command line tool.

string

colon separated classpath

Arguments

array of strings

arguments to main

String[] passed to main.

string

space separated arguments to main

Properties

dictionary

key/value pairs

All key/value pairs in the dictionary are added as initial properties to the Java VM (same as -D key=value) on the java command line. Both the key and value in the dictionary must be of type string.

VMOptions

array of strings

vm option

Miscellaneous VM options (e.g -Xms2m)

string

space separated vm options

WorkingDirectory

string

path

Some Java code expects various data files to be found relative to the current working directory. By default, the cwd is set to be the parent directory of the .app package. In order to make such a Java program work when the data files are stored inside the .app directory, use this option to change the cwd (e.g. $APP_PACKAGE/Contents/Resources).

$JAVAROOT

string

path

If this key is not specified, $JAVAROOT defaults to $APP_PACKAGE/Contents/Resources/Java. $JAVAROOT is purely a convenience to reduce the length of strings in the Info.plist file. Note: $JAVAROOT and $APP_PACKAGE are only expanded by the java launcher code. They are not usable from Java code. They will expand when used in the string values for the keys: Jar, ClassPath, Arguments, Properties, WorkingDirectory, and VMOptions.

Java properties in MRJApp.properties

The MRJApp.properties file is stored inside a .app package in the Contents/Resources/ directory. Its format is that of a standard java .properties file. Any property name that begins with com.apple.mrj.application is used to configure Java. All other properties are passed onto the VM as initial properties (i.e. -D prop=value).

The following is a table of properties which affect the launch:

Property

Value

Comments

com.apple.mrj.application.classpath

classpath

Colon-separated list of classpath entries.

com.apple.mrj.application.main

class name

Name of class whose public static void main(String[]) should be run. If the class is in a package, it you must specify the dot-separated full class name (e.g. com.apple.SurfWriter)

com.apple.mrj.application.parameters

arguments

Space-separated list of arguments which are parsed to build the String[] passed to main.

com.apple.mrj.application.workingdirectory

path

Sets the current working directory for the application.

com.apple.mrj.application.vm.options

option(s)

Space-separated list of options to VM (e.g -Xms2m)

Known bugs:

Localizing packaged Java applications on Mac OS X

In order to run correctly on Mac OS X in non-English locales, packaged Java applications need to have the appropriate .lproj folders inside the application package. This is true even if the Java application handles its localization through Java ResourceBundles.

Specifically, you need to have a localename.lproj folder present in the application’s Resources folder for any locale that you wish to use. For example, you need a Japanese.lproj folder inside Appname.pkg/Contents/Resources/ in order for Japanese localization to work correctly.

These .lproj folders can be empty, but a folder corresponding to the current locale must be present in order for Mac OS X to set the locale correctly when the application launches. If you do not have a .lproj folder that corresponds to the current system locale, your application will be launched with the English US locale.

See the Bundle Services Documentation for more details about .lproj folders and the application bundle format.

Specifying a Dock name and icon for command line Java applications

If you are running an application from the command line that has a user interface, we now use the name of your application’s main class as the application name that appears in the Dock. Alternatively, you can specify the name and/or icon that will used by using the following command-line option:

-Xdock:name=<application name>[:icon=<path to icon file>]

The icon file must be an icns file, identical to what you would use for any other Mac OS X application. If either the application name or path to the icon file has spaces in it you can wrap each option in double quotes and specify multiple -X:dock options. Only the first of each kind ('name' and/or 'icon') will be recognized.

Java Web Start

This release of Java for Mac OS X contains Java Web Start. It is a product-quality reference implementation (RI) of the Java Network Launching Protocol & API (JNLP) Specification, v1.0.1. To find out more about Java Web Start, see Java Web Start on Mac OS X, or try the sample applications available when you launch the application.

Apple’s implementation of Java Web Start differs from the Windows and Solaris versions in the following ways:

Java Web Start caches its data in your login directory in the hidden directory .javaws. Removing this directory or clearing the cache can free up hard disk space.

Java Web Start with JBuilder

The version of JBuilder for Mac OS X that was distributed at WWDC 2001 has a bug in its Web Start Launcher wizard that causes an incorrect .jnlp file to be generated. It inserts a tag for the version like this:

<j2se version="1.3.1+">

A version tag in this format is a 'platform version' tag, not a 'product version' tag. As a result, Web Start apps generated by JBuilder won’t run unmodified because they are requesting the non-existent 1.3.1 Java platform. Instead this version tag should be "1.3+" to get the Java2 platform v1.3. You will need to modify the generated .jnlp file to work on Mac OS X.

Apache config and Web Start

Apache does not ship configured to serve Web Start files. To fix this, add this entry to Apache’s mime.types file:

application/x-java-jnlp-file jnlp

and restart the web server.

Java Web Start and Internet Explorer

If your download location is located on an NFS-mounted server, Internet Explorer will not automatically open JNLP files after they are downloaded (this applies to all downloads, not just JNLP files). To work around this problem, change your download location to some place other than the NFS-mounted server.

Applet Launcher

Applet Launcher allows you to run Java applets without the overhead of launching a web browser. Applet Launcher provides a graphical user interface to the sun.applet.AppletViewer class, with more features than the appletviewer command-line tool from Sun, which is based on the same class. You can enter the path to an applet using its fully-qualified URL, and then press the Launch button. For example, entering the following URL will launch the Sun Tumbling Duke example applet:

http://java.sun.com/applets/other/TumblingDuke/index.html

Applet Launcher has an Applets menu that displays all applets listed in the /Developer/Examples/Java/Applets directory. These applets are provided by Sun Microsystems as examples.

Launching java from the command line

JDK-style command-line launching from the Terminal app is fully supported (as are all your favorite JDK tools like javac and rmic). You can still use "java" to launch apps and "appletviewer" to launch applets. (Invoking these with no arguments will print a brief help message.) The Terminal window serves as the Java console. You can kill a Java process by activating the Terminal window that launched it and pressing Ctrl-C.


10.1.web.7 t 20011003

Copyright © 2001 Apple Computer, Inc.