Java Embedding Plugin Readme (12/2006)

  1. What is the Java Embedding Plugin?
  2. Requirements
  3. Installing and Uninstalling the Binaries
  4. How Does the Java Embedding Plugin Work?
  5. Debugging and Troubleshooting
  6. Known Problems
The Java Embedding Plugin was written by Steven Michaud (smichaud at pobox.com)

I) What is the Java Embedding Plugin?

The Java Embedding Plugin is a utility that allows other web browsers than Apple's Safari to use the most recent versions of Java on Mac OS X (Java 1.4.X on OS X 10.2.8 through 10.4.X, and Java 1.5.0 (aka J2SE 5.0) and Java SE 6 on OS X 10.4.X). When used together with an updated version of Mozilla's MRJ Plugin Carbon (included in this distribution), the Java Embedding Plugin's functionality is currently available to recent versions of Mozilla, Firefox and Camino. But in principle any web browser could use one of the Java Embedding Plugin's two APIs to add support for Java 1.4.X and (where available) 1.5/5.0 and 6.

Apple's older Java versions (1.3.1 and earlier) have a documented API for use by browser developers -- the Java Embedding API, exported by the Java Embedding Framework. (As of OS X 10.2, developers can also use the "Java Applet Plugin", which exports a Netscape 4 plugin API. This is just a shim on top of the Java Embedding Framework.) But Apple has never documented a realistic way for browser developers to support more recent Java versions. (Apple does provide a high-level Web Kit API for use by application developers who want to embed web content in their applications, but existing browsers would have to be completely re-written to use this.) This is an unfortunate state of affairs, and I've decided to do something about it.

The Java Embedding Framework has two APIs -- one for C programmers (suitable for either Carbon or Cocoa browsers) and one for Objective C programmers (suitable for Cocoa browsers). The C API is closely modeled on Apple's Java Embedding API, but with some additions and modifications to fill its gaps and to make it usable with the newer Java versions. (See JavaEmbeddingPlugin.h in the source distribution for more information on the C API. The Objective C API has no documentation yet, and is still changing from version to version.)

To make the Java Embedding Framework usable "out of the box" in at least some existing browers, I've dusted off Mozilla's old MRJ Plugin Carbon, fixed a bunch of bugs, and added support for the Java Embedding Framework. This support is "conditional" -- you can use the new MRJ Plugin Carbon with or without the Java Embedding Plugin. If you use it without the Java Embedding Plugin, the "MRJ Plugin JEP" falls back to using the older Java versions.

II) Requirements

The current versions of the Java Embedding Plugin and the MRJ Plugin JEP have been tested on OS X 10.2.8 with Java 1.4.1, on OS X 10.3.9 with Java 1.4.2_09 (Java Security Update), and on OS X 10.4.8 with Java 1.4.2_09 and Java 1.5.0_06 (i.e. J2SE 5.0 Release 4), and with Java SE 6 (Release 1 Developer Preview 6). The only browsers that will currently work with these combinations are recent versions of the Mozilla Suite, Firefox, Camino and Seamonkey (i.e. browsers that can use the MRJ Plugin Carbon, which is an "OJI Plugin"). Only fairly recent versions of those three browsers have been tested -- Mozilla 1.6 and 1.7.X, Firefox 0.8 through 2.0, Camino 0.7 through 1.0.3 and Seamonkey.

The Java Embedding Plugin is now bundled with Firefox 1.5.0.X, Firefox 2.X, Camino 1.X and Seamonkey. So if you're using one of these browsers, you don't need to install the Java Embedding Plugin, though you may wish to replace the bundled version of the Java Embedding Plugin with a more recent version (for which see the next section).

Apple's Java 1.4.2 and above have one additional requirement, unrelated to the Java Embedding Plugin -- an appropriate version of the JavaPluginCocoa.bundle must be present in the /Library/Internet Plug-Ins folder.

The two parts of the Java Embedding Plugin are now distributed as "universal binaries" -- suitable for use on either PPC-based or Intel-based Macintosh computers. But older versions of Mozilla.org browsers (Firefox 1.0.8 and earlier, Mozilla 1.7.13 and earlier, Camino 0.8.5 and earlier) can't use universal binary plugins. So the Java Embedding Plugin is also available (in the distribution) as PPC binaries.

III) Installing and Uninstalling the Binaries

To install the Java Embedding Plugin (JavaEmbeddingPlugin.bundle) and the MRJ Plugin JEP (MRJPlugin.plugin), drag them to the /Library/Internet Plug-Ins folder. (If your Mozilla.org browser is old enough not to work with universal binary plugins, you will need to use the PPC-binary copies of these files.) Then check the timestamps (the time last modified) of MRJPlugin.plugin and the following two files (which should also be present) -- Java Applet.plugin and Java Applet Plugin Enabler. (The easiest way to see these files' timestamps is to switch to the "list" view.)

If MRJPlugin.plugin doesn't have the most recent timestamp, you will need to change it. One way to do this is to open a Terminal session and enter the following command, which sets MRJPlugin.plugin's time last modified to the current time:

touch "/Library/Internet Plug-Ins/MRJPlugin.plugin"

To uninstall the binaries, drag them out of the /Library/Internet Plug-Ins folder.

If you wish you can use the MRJ Plugin JEP without the Java Embedding Plugin. (This is very useful for testing purposes.) To do this drag JavaEmbeddingPlugin.bundle out of the /Library/Internet Plug-Ins folder but leave MRJPlugin.plugin in place. The MRJ Plugin JEP will fall back to using Java 1.3.1.

If you are upgrading the version of the Java Embedding Plugin that was bundled with your copy of Firefox 1.5.0.X, Firefox 2.X, Camino 1.X or Seamonkey, you also need to remove the old version from your browser:

  1. Control-click on your browser and choose "Show Package Contents".
  2. Browse to the Contents/MacOS/plugins directory and delete JavaEmbeddingPlugin.bundle and MRJPlugin.plugin.

If you mostly use newer Mozilla.org browsers (Firefox 1.5.X or 2.X, Camino 1.X, Seamonkey), but also sometimes use older versions (ones that don't work with universal binary plugins), it's probably best to copy the Java Embedding Plugin's PPC-binary files to those older versions' Contents/MacOS/plugins directories.

IV) How Does the Java Embedding Plugin Work?

The Java Embedding Plugin works at a low level -- the same as that of Apple's old Java Embedding Framework (which still provides Java 1.3.1 functionality) and the "OJI Plugin" that Sun makes available with its Java Plugin on other platforms (but which Apple chose not to port). Basically, it uses the (C-based) Java Native Interface to bootstrap the JVM, then uses Java code to create an environment that can host an applet. For Cocoa-based browsers (like Camino) that's pretty much all that's needed. But much more is required to support Carbon-based browsers (like Firefox and Seamonkey).

The problem is that all the drawing code in Apple's recent versions (1.4.X and 1.5/5.0) of Sun's JVM is Cocoa-based, but the drawing models for Carbon and Cocoa are quite different. Apple does provide a Cocoa-Carbon interface (partially documented in their "Integrating Carbon and Cocoa in your Application"). But this is, quite frankly, crawling with bugs, and even Apple tries to discourage people from using it to do anything serious -- i.e. to mix Cocoa and Carbon "widgets" in the same window.

For us to support Java 1.4.X and 1.5/5.0 in Carbon-based browsers, we must "mix Cocoa and Carbon widgets in the same window". Fortunately I've found workarounds for all the bugs in the Cocoa-Carbon interface that I've been able to diagnose -- I use a combination of Carbon event handlers and subclassed Cocoa "system" classes (via poseAsClass or its equivalent).

The Java Embedding Plugin uses many undocumented APIs in the AppKit Framework and in Apple's Java Virtual Machine (whose code is in the JavaVM Framework). I make no apologies for this -- without it my work would have been impossible. But it means that the Java Embedding Plugin is more likely to break on future releases of OS X and of Apple's JVM than an app that uses only published APIs.

However I'm not too worried about this. Between Java 1.4.1 on OS X 10.2.8 and Java 1.4.2_09/1.5.0_06 on OS X 10.4, Apple made only three changes that required substantial changes to the Java Embedding Plugin: With Java 1.4.2 Apple changed the size (from 32-bit int to 64-bit long) of many Java-code variables and parameters that reflect Cocoa-code pointers (this was presumably done to add 64-bit support to Apple's JVM). With Java 1.4.2 Update 1 they removed code that had been displaying some Java objects on a "third thread" (display of Java objects was consolidated on the "second thread" code that came from Sun's original JVM that Apple has licensed). And with Java 1.4.2_07 (what I call "Java 1.4.2 Tiger"), they forced all Java drawing code off the main thread. If change continues at this pace, it should be fairly easy to keep the Java Embedding Plugin current.

Early (unreleased) versions of the Java Embedding Plugin used the (also undocumented) JavaPluginCocoa.bundle in the /Library/Internet Plug-Ins folder. But I quickly found myself replacing most of its code to fix bugs. So I decided to (as much as possible) do without it. If the JavaPluginCocoa.bundle is present, the Java Embedding Plugin does still use JNI and Java code from inside it (contained in the files JavaPluginCocoa, libAppletsInCocoa.jnilib and/or AppletsInCocoa.jar), but can also function without it. However, as of Java 1.4.2, Apple's own JVM requires a lot of the code contained in these files, and will not function correctly without it.

V) Debugging and Troubleshooting

The Java Embedding Plugin is a beta app that heavily depends on undocumented APIs. So there will be problems, and I need your help to fix them. But the Java Embedding Plugin won't suddenly become the cause of all the problems on your computer :-) So you need to work a bit to winnow out the problems that have other causes. Fortunately this is very easy.

If you have a problem with an applet in one of the browsers that the Java Embedding Plugin currently supports (Firefox, Camino or Seamonkey), first look in the following file in your home directory -- ~/Library/Logs/Java Console.log. This file is created by the MRJ Plugin, and contains a record of your most recent Java "session" -- including any Java exceptions that may have occurred. Another way to view Java exceptions is to run the Java Control Panel (Java 1.4.X Plugin Settings in the /Applications/Utilities/Java folder, or Java Preferences in the /Applications/Utilities/Java/J2SE 5.0 folder) and choose "Show console" (though this will cause less information to be written to Java Console.log).

As of version 0.8.8, the Java Embedding Plugin logs to the Java Console whenever it creates an applet (each entry will contain a timestamp and (at least) the text "JEP creating applet [name]"). If your console log doesn't contain one or more recent entries for applets created, then either they weren't loaded or the current page doesn't contain any applets.

If it's really an applet that you're having trouble with, try the same applet in the other supported browsers and in Safari, and (if possible) on different platforms (e.g. in some browser on Linux or Windows).

An applet problem that occurs in Safari, Firefox, Camino and Seamonkey, but not on other platforms using the same version of the Sun's Java Plugin, is likely to be a problem with Apple's implementation of Sun's JVM. A problem that also occurs on other platforms using Sun's Java Plugin is likely to be a problem with Sun's JVM ... or even possibly with your applet :-)

An applet problem that occurs in Firefox, Camino and Seamonkey, but not in Safari, may be a problem with the Java Embedding Plugin, the MRJ Plugin JEP, or possibly the browser itself. Try temporarily dragging JavaEmbeddingPlugin.bundle out of the /Library/Internet Plug-Ins folder but leaving MRJPlugin.plugin in place (the JEP will fall back to Java 1.3.1). If the problem disappears, the cause is most likely somewhere in JavaEmbeddingPlugin.bundle. If it doesn't disappear try dragging MRJPlugin.plugin out of the /Library/Internet Plug-Ins folder (your browser will use Java 1.3.1 via the "Java Applet Plugin"). If this makes the problem disappear, the cause is probably in the MRJ Plugin JEP. If the problem still doesn't disappear, it may be due to a bug in your browser.

An applet problem that occurs in Firefox and Seamonkey but not in Camino is likely to be caused by a problem in the Carbon-specific code of the Java Embedding Plugin. Likewise an applet problem that occurs in Camino but not the other two browsers is likely to be caused by something in the Cocoa-browser-specific code of the Java Embedding Plugin (there actually isn't much Cocoa-browser-specific code, but the absence of some fix in the Carbon-specific code might be causing trouble).

If possible, try the applet in different versions of Apple's JVM. I've seen some Apple-specific problems (i.e. ones not found in similar versions of Sun's JVM on other platforms) disappear with the change from 1.4.1 to 1.4.2, and more still disappear with 1.4.2 Update 1.

If the problem isn't associated with an applet, it's likely not to have anything to do with Java or the Java Embedding Plugin :-)