Mac OS X bundles Suns 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 Apples 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.
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).
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.
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.
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.
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
-X
optionname
. For a list of these
options, type java -X
in a Terminal window.
The HotSpot VMs 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.
Some notable Java system properties include:
Name Value Comments 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
This was "1.1" (the version number of the
Darwin kernel) in early pre-releases of Mac OS X. 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. 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.
os.name
Mac OS X
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
mrj.version
3.1
line.separator
'\n'
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.
user.language
and
user.region
, defined on the java
command
line, or in MRJAppBuilder property settingsLC_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.LANG
environment variableSpecifying a locale within Java code using
Locale.setDefault(
newLocale
)
can be done after the VM is running, and overrides all other
options.
Java debugging is now fully operational in Project Builder, and is the recommended way to debug your Java applications.
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.
Currently, "/usr/bin/java" is a script. Because gdb wont recognize the script as an executable format, you cant 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:
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
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):
-XX:+JavaMonitorsInStackTrace
on the java
command line..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.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.
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.
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.
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
lib
name
.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 lib
name
.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.
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
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, couldnt 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
windows 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.
Our Graphics/Java2D implementation is based on Apples 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:
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:
To allow developers more flexibility in dealing with Mac appBundles and packages, weve 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. Theyre 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.
Known problems with event handling:
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 windows 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).
Unsigned applets cant 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";
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.
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()).
Java on Mac OS X supports sound output. However, audio input is not currently supported.
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.
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 its 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, dont 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.
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 applications 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
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.
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.
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.
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.
The MRJToolkit utility routines from MRJ on Mac OS 9 are present in this release, but there are differences.
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.
The MRJ
Thing
Handler
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
applications 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();
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:
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.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 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:
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 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 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 youre 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 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 applications
Contents/Resources/Java/
directory. Each item you add to
the merge list gets automatically added to the classpath.
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,
youll 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).
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
youve 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
Lets 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 nameHelloWorld
, since there is only one class containing amain()
method. Click "OK". The main classname field should be automatically filled out and the classpath updated with the itemContents/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 dont 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 dont 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". Thats 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:
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.
Java
keyMRJApp.properties
file in the
applications Resources
directoryEither 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.
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 string jar file path Same as the string fully qualified class name Name of class whose array of strings classpath entries Same as the string colon separated classpath array of strings arguments to main string space separated arguments to
main 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. array of strings vm option Miscellaneous VM options (e.g
-Xms2m) string space separated vm options 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.
string path If this key is not specified,
$JAVAROOT defaults to
Jar
-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
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
-classpath
option to the java command line tool.
Arguments
String[]
passed to
main
.
Properties
VMOptions
WorkingDirectory
$APP_PACKAGE/Contents/Resources
).
$JAVAROOT
$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.
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 classpath Colon-separated list of classpath
entries. class name Name of class whose arguments Space-separated list of arguments which
are parsed to build the path Sets the current working directory for
the application. option(s) Space-separated list of options to VM
(e.g -Xms2m)
com.apple.mrj.application.classpath
com.apple.mrj.application.main
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
String[]
passed
to main
.
com.apple.mrj.application.workingdirectory
com.apple.mrj.application.vm.options
Known bugs:
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 applications 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.
If you are running an application from the command line that has a user interface, we now use the name of your applications 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.
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.
Apples 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.
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 wont 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 does not ship configured to serve Web Start files. To fix this, add this entry to Apaches mime.types file:
application/x-java-jnlp-file jnlp
and restart the web server.
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 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.
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.
Copyright © 2001 Apple Computer, Inc.