ADC Home > Documentation > Release Notes

Mac OS X 10.0 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, including the client version of HotSpot.

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

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


Java and Microsoft Internet Explorer 5.1 Preview Release

Mac OS X includes MSIE 5.1 Preview Release. Many Java applets have problems with this version of MSIE. We are working with Microsoft to improve applet behavior in MSIE on Mac OS X.


Topics


Java Virtual Machine

Mac OS X ships with the client version of the HotSpot virtual machine from the JDK 1.3 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 or VolanoMark.

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 earlier versions of MRJ. 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.0

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

mrj.version

3.0

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 previous versions of MRJ, 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. See the Project Builder documentation for more details.

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/Commands/java

In the future, "/usr/bin/java" will be restored to a symbolic link.

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

(gdb) setenv CLASSPATH foo:bar
(gdb) run nameofjavaclass arguments

The VM exports two useful functions for use inside gdb. The ps function prints the Java stack of the current thread, and the pss function prints the stacks of all Java threads:

(gdb) call (void)ps()
(gdb) call (void)pss()

Here is sample output from pss():

    "Thread-1" prio=5 tid=0xbb810 nid=0x13d3510 waiting on monitor [0x1777000..0x1777b68]
at java.lang.Object.wait(Native Method)
- waiting on <222d1260> (a sun.misc.TimerTickThread)
at java.lang.Object.wait(Object.java:420) at sun.misc.TimerTickThread.returnToPool(Timer.java:608) at sun.misc.TimerTickThread.run(Timer.java:630) "TimerThread" prio=5 tid=0xb9020 nid=0x13d2ca0 runnable [0x16c8000..0x16c8b68] at java.lang.Object.wait(Native Method) - waiting on <222d1220> (a sun.misc.TimerThread) at sun.misc.TimerThread.run(Timer.java:371) - locked <222d1220> (a sun.misc.TimerThread) "SunToolkit.PostEventQueue-0" prio=6 tid=0xb8380 nid=0x13af970 waiting on monitor [0x15d7000..0x15d7b68] at java.lang.Object.wait(Native Method) - waiting on <222d2f00> (a sun.awt.PostEventQueue) at java.lang.Object.wait(Object.java:420) at sun.awt.PostEventQueue.run(SunToolkit.java) - locked <222d2f00> (a sun.awt.PostEventQueue) "AWT-EventQueue-0" prio=6 tid=0xb7900 nid=0x13af710 waiting on monitor [0x1556000..0x1556b68] at java.lang.Object.wait(Native Method) - waiting on <222d3258> (a java.awt.EventQueue) at java.lang.Object.wait(Object.java:420) at java.awt.EventQueue.getNextEvent(EventQueue.java) - locked <222d3258> (a java.awt.EventQueue) at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java) at java.awt.EventDispatchThread.run(EventDispatchThread.java)

Note that the stack traces above show monitor status. There are several ways to enable this option (this applies also to all other -XX: based VM options):

  • Pass -XX:+JavaMonitorsInStackTrace on the java command line.
  • Create a .hotspotrc file in your home directory. This file gets parsed every time a Java VM starts up, so this gives you a way to set options even for double-clickable binaries or when embedding within another application. Include a line containing: +JavaMonitorsInStackTrace in your .hotspotrc file.

To print the current stacks without having to run inside gdb:

  • If the Java program was launched from the commandline, you can press CTRL-\ to generate a SIGQUIT, which ends up printing the current stack frames to the output.
  • If the Java program was launched from the Finder, find its PID using the ps command line tool, then deliver a SIGQUIT to that process. Here is the command sequence:
    $ ps -auxwww | grep "Applet Launcher"
    user 557 0.2 6.2 211952 16236 ?? S 0:06.47 /Applications/.../Applet Launcher -psn_0_1703937
    user 559 0.0 0.1 5724 188 std UV+ 0:00.00 grep AppletLauncher
    $ kill -QUIT 557

Please 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.

If you are reporting a bug that results in a crash or a deadlock, please reproduce the bug while running in gdb, call pss(), and include the thread dump in the bug report. In case of a crash, also include the native stack trace printed by the bt command. To get all native backtraces, use the gdb command "thread apply all bt".

See the gdb man page for more details.


Profiling tools

Java on Mac OS X provides hprof as a basic profiling tool. While the CPU timing it provides is useful, the monitor output is unreliable and we do not recommend its usage for contention analysis. This will be improved in a later release.

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


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 System 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


Building native applications that launch the Java VM

To build a C application that starts a Java VM sesssion, you must link with the JavaVM framwork. e.g.

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


AWT and other class libraries

The AWT implementation is a Carbonized version of the one in MRJ 2.2.4, extended to support Java2.

Windows and Dialogs

Window resizing is "live" by default. To disable this behavior, see the section on GUI customization.

Window titles, controls, menu titles and menu items can now use any Unicode characters supported by Mac OS X. (In previous versions of MRJ, 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 now 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 earlier MRJs.) 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 generic document icon, even though they're applications (currently, if more than one java process is launched from the command line, only one icon shows up in the Dock). 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.

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 -- as opposed to the JDK, which drops down to GDI or X-Windows for simple 1.1-style drawing -- and while Quartz is very fast at complex rendering, it has not yet been optimized for some basic shapes like diagonal lines.

For complex graphics, our Java2D implementation has up to 5x the performance of Sun's implementation, but simple Java-1.1-style graphics performance is significantly below that of MRJ 2.2.x, although better than in Mac OS X previews.

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.

Compatibility issues to note:

  • Drawing shapes over each other when anti-aliasing is on may cause different results than in Java 1.1. For instance, drawing a white line on top of a black line will not completely erase the line; the compositing rules leave some gray pixels around the edges. (The JDK "Clock" applet exhibits this glitch.) Also, drawing text multiple times in the same place will cause the partially-covered pixels along the edges to get darker and darker, making the text look smudged.
  • Java on Mac OS X will never have pixel for pixel match with the Sun Java2D implementation, especially when anti-aliasing is on (see the GUI Customization section below for information on how to disable anti-aliasing for ) . Quartz's anti-aliasing algorithms for both line art and text are different than Sun's default implementations, so the rendered pixels will not match exactly. Apple is using the Quartz graphics system because it improves drawing quality over other platforms' Java2D implementations.

Known bugs:

  • There are a few situations in which JPEG images won't be read properly.
  • Using a Shape object for drawing perfectly horizontal or vertical lines (rather than calling drawLine()) will hit a serious bug that hangs the Java process, and may even require a reboot. The workaround is to use drawLine() in these cases, which is the more common approach.

Swing

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 now 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:

  • The default for the Mac OS look and feel is to leave all Swing menus in the window. If you wish to move the main Swing menu bar (the JMenuBar blessed by JFrame.setJMenuBar) into the Mac menu bar, see the GUI customization section.

Known bugs:

  • JMenuBars in JDialogs are not moved to the Mac menu bar.
  • Using the striped backgrounds from the Aqua look-and-feel can sometimes cause redraw problems.

Event handling

Known problems with event handling:

  • If a multi-button USB mouse is connected, the extra mouse buttons will behave exactly like the main one; they won't invoke contextual menus and the META modifier will not be set in MouseEvents. This appears to be a limitation of the current USB mouse driver; it affects Carbon and Cocoa apps as well.

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.useMDEF

true

Uses a custom Carbon menu definition (MDEF) for Swing menus in the Mac menu bar. This allows Swing menus to draw arbitrary content.

com.apple.macos.useScreenMenuBar

false

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

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

true

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.

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";

AWT internal permissions required for RMI clients

If you are running an AWT-based application as an RMI client, you may encounter security exceptions when you launch the application. To work around this, add the following entries to your system-wide java.policy file, which is located at ${JAVA_HOME}/lib/security/java.policy:

java.util.PropertyPermission "com.apple.openglactive", "read";
java.util.PropertyPermission "macosx.aatextactive", "read";
java.util.PropertyPermission "macosx.fmtextactive", "read";
java.util.PropertyPermission "com.apple.macos.xUseQD", "read";
java.util.PropertyPermission "com.apple.macos.xDontUseWindowGroups", "read";
java.awt.AWTPermission "accessEventQueue", "";

This can be done in the section for all code, or on a case-by-case basis in a separate policy file you specify on the command line.

Other known problems with RMI:

  • 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.

Sound

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


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 GM no longer supports the synchronization method (Toolbox.LOCK) described in the Public Beta Java release notes. The correct way to call the Toolbox (aka Carbon) from Java on Mac OS X GM 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--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 from the command line, 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 2.x on Mac OS 9) with a Carbon-based Java embedding API. JManager is not supported in Mac OS X. The interfaces to the new API are the headers <JavaVM/JavaApplet.h>, <JavaVM/JavaControl.h> and <JavaVM/JavaErrors.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 call CreateSafeEnvironment() on the main thread.

Only native applications that want to embed a Java frame into their own windows need to use the new Java Embedding control creation APIs in <JavaVM/JavaControl.h>. These create a "Java Control" -- a standard Control Manager control that contains a Java applet. The control creation APIs take a native WindowRef that references the window into which the Java Control is to be embedded.

Known problems with the Java Embedding API:

  • There are a number of clipping problems in the current release.


MRJToolkit

The MRJToolkit utility routines from previous versions of MRJ 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:

  • Your MRJQuitHandler cannot directly field events. For instance, you cannot run a modal dialog which asks the user to confirm the Quit. The workaround is to create a new thread and run the modal dialog on it.
  • Java applications may not automatically quit on Log Out/Shut Down/Restart, even if you have an MRJQuitHandler.


Developing, packaging, and launching Java

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 is settable 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--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 configurations file defining the Java runtime properties. This panel is a replacement for the configurations 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 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/myApp.app/. As a result, all of your classpath entries for jar files merged into your application would be of the form Contents/Resources/Java/myApp.jar. Note that the Contents folder resides directly inside myApp.app.

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:

  • Drag and Drop is currently not supported in MRJAppBuilder.
  • There is no indication that MRJAppBuilder has finished creating the output application.
  • In some cases, MRJAppBuilder may fail to create an application, but will not report errors. A known case of this is when you do not have permissions to write the output file.
  • There are problems editing the merge list and classpath in some cases.
  • Once a jar file and main class are selected, you have to quit and relaunch MRJAppBuilder to select a main class from a different jar file.
  • Adding individual class files doesn't work well, since the classpath entry that is automatically generated is incorrect. Add jar files instead, or you can try to fix the classpath entries by hand.
  • Watch the output in the Console application for errors and information when diagnosing problems with MRJAppBuilder.

Applet Launcher

Applet Launcher allows you to run Java applets without the overhead of launching a web browser. Applet Launcher provides a user interface around 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.

Known problems with launching from the command line:

  • When run from the command-line, Java applications that weren't built with MRJAppBuilder may not show up in the Dock.

6.11 t 20010319

Copyright © 2001 Apple Computer, Inc.