Editor's note: Recently, James Duncan Davidson published a series of weblogs on the subject of Java and Mac OS X for O'Reilly Network. These 'blogs contained lots of useful information that was too good to get buried deep within the network labyrinth, so we've updated them and are now presenting the content in a series of three articles. This is part two of that series.
In this article Davidson discusses MRJAppBuilder and application bundle internals, experiences with Project Builder, and fun with Quartz.
The easiest way of creating a double-clickable Java program on Mac OS X is to use Apple's MRJAppBuilder. It creates a nifty bundle which contains all of the class and resource files needed by an application, as well as some information that helps Mac OS X run it. Unfortunately, the documentation on this tool is not as accessible, or as clear, as one might like. In a very uncharacteristic move for Apple, there isn't even a help menu.
Luckily, MRJAppBuilder is not very hard to use. After a couple of runs with the tool, I have come up with the following easy to use recipe:
After following the above process, you will have an application ready to use or distribute. To be more accurate, you will have an application bundle. This bundle will look to users, via the Finder, like a single file, which aids its ease of use and distribution. But under the covers is an interesting hierarchy of files that contain the secrets of how your Java application is run when you double-click on it.
You can dig into the innards of your application bundle in one of two ways. The first is to control-click on the bundle and select Show Package Contents from the pop up menu. This will open up a Finder window that you can browse the contents of the bundle with. The other way is to dive in using the Terminal. Just cd [appname].app (the .app extension is hidden by the Finder, but all application bundles have it). The following is an example of one of the application bundles that I created using MRJAppBuilder:
MRJTest.app/
MRJTest.app/Contents
MRJTest.app/Contents/Info.plist
MRJTest.app/Contents/MacOS
MRJTest.app/Contents/MacOS/JavaApplicationStub
MRJTest.app/Contents/Resources
MRJTest.app/Contents/Resources/GenericJavaApp.icns
MRJTest.app/Contents/Resources/MRJApp.properties
MRJTest.app/Contents/Resources/Java
MRJTest.app/Contents/Resources/Java/MRJTest.jar
The Info.plist file is an XML-based description of some basic information that Mac OS uses to run the application. Most of the information in this file only makes sense if you have experience with building native Mac OS applications. The key configuration data it contains (for our purposes) tells the system to execute the JavaApplicationStub executable in the bundle. This stub is a very simple program that it copied from the JavaVM.framework. It looks at the MRJApp.properties file and then starts up a Java virtual machine based on the configuration information it finds there. Here are the important properties from my application:
com.apple.mrj.application.main=com.x180.test.MRJTest
com.apple.mrj.application.classpath=
Contents/Resources/Java/MRJTest.jar:
com.apple.mrj.application.parameters=
com.apple.mrj.application.stdin=/dev/null
com.apple.mrj.application.stdout=$SYSTEM
com.apple.mrj.application.stderr=$SYSTEM
com.apple.mrj.application.profiling=false
|
Previously in this series: |
Having access to all of this information in plain text files means that I can continue to use this created bundle even as my application is updated. For example, if I need to add a library in a Jar file, I can copy it into the Contents/Resources/Java directory of the bundle and add it to the classpath entry in the properties file. Even better, since the application bundle format is so simple, it is possible to set up a few simple build scripts and have bundles created on demand from automated build tools. This bypasses the need to manually execute MRJAppBuilder and recreate application bundles every time a program is updated.
|
The centerpiece application on the Developer Tools CD that ships with standalone versions of Mac OS X is an Integrated Development Environment (IDE) called Project Builder. This is a new effort from Apple that is adept for writing C-based kernel modules, Objective C Cocoa applications, C++ based I/O drivers, and general purpose Java work. Unlike most Java-capable IDEs, it launches quickly and doesn't completely take over your monitor with tool bars and windows.
When I say that it launches quickly, I mean that it launches extremely fast, compared to most of the other IDEs on the market. On my PowerBook G4, Project Builder is ready for action less than five seconds after double clicking on the application's icon. Contrast this to other Java capable IDEs that take half a minute, a minute, or more to launch. To be fair, Project Builder doesn't sport some the feature list of other IDEs. Notably, it leaves interface building to external applications. And that is fine by me, as I have been asking IDE makers to make a simpler tool for a long time, one that I can edit, build, and debug code in. Project Builder delivers just this and does it fairly well.
Project Builder comes with starter projects for writing Java applets, Java AWT-based applications, Java Cocoa-based applications, and a generic Java project type called "Java Tool." All of these starter projects are set up to easily build reasonable products. In fact, the Java AWT-based application builds MRJ-based application bundles of the type that I described in my last weblog entry.
But what if you don't want to start a new project? What if you want to use Project Builder to work on an existing project? I wrestled with this for a while until one of the Apple developers turned me onto the misnamed "Legacy Makefile" target. The trick is to create a new target of this type, and then customize it to do execute whatever command you need to. The target takes essentially three important pieces of information:
With this target, you can execute any command you want anywhere on your system. Really, this should have been named the "Custom Build Command" target type. After finding this out and setting it up to use my own build tools, I have found myself doing most of my day-to-day Java coding in Project Builder.
Not withstanding the good points, Project Builder is a freshman effort, and there are several rough spots that I hope Apple fixes soon. One such rough spot is that break point makers don't maintain their relative position as you edit the code that they point to. This means that when I'm in a debugging session, and editing code, I have to keep adjusting my break points.
There also seems to be an intermittent performance issue when debugging Java code. So far, it only seems to strike me when my laptop is configured with a hostname that cannot be resolved (for example, when I unplug from a DHCP network). If I have my hostname set to localhost, debugging works fine. I haven't conclusively proven this yet, and your mileage may vary, but it seems to work for me. Apple's developers are aware of the issue and have said that they have a fix in the works.
Even with the rough spots, Project Builder is a nice tool. If Apple keeps improving it, I may have finally found a lightweight, fast, easy-to-use IDE that satisfies, something that no IDE yet has been able to do for me.
A lot of graphics magic happens in Mac OS X to make the UI go together the way it does. In fact, I'm still scratching my head wondering how it's all done so well. To help peek behind the curtain, Apple has provided a tool that at least gives a glimpse into the magic that Quartz performs. It's called "Quartz Debug" and it can be found in the Developer folder after you install the Developer Tools CD.
When you launch Quartz Debug, a simple window is displayed. Enable the Flash Screen Updates and No delay after flash checkboxes and then use your system as normal. Every screen update is preceded by a yellow flash which lets you see what Quartz is redrawing. This is most impressive when mousing over the dock with magnification enabled. As the icons are scaled, you can see the exact set of pixels that are getting recalculated.
Of course for most users and developers, seeing this in action is more fun than actually useful. But I found it to be an interesting view into how Mac OS X works. Enjoy the show!
James Duncan Davidson is a freelance author, software developer, and consultant focusing on Mac OS X, Java, XML, and open source technologies. He currently resides in San Francisco, California.
Return to the Mac DevCenter.
Copyright © 2009 O'Reilly Media, Inc.