Applet writers under pressure to target the largest possible audience must confine themselves to the 1.1.4 Microsoft VM. This demo shows how to set rendering hints (which is a Java2 feature not present in the MS VM) and still run in the Microsoft environment.
This code (AntiAliasEnabler.java and AntiAliasEnablerDemo.java) demonstrates the use of a single class called AntiAliasEnabler with a single public method called setAntiAlias which allows you to turn anti-aliasing on (or off) if the applet is running under Java2 and do nothing running under the MS VM. This demo contains text with and without anti-aliasing. It also draws a rounded rectangle around the text which shows rendering hints working for non-text drawing as well. If your version of Java displays something other than what the text is saying on the screen please let me know. My email is michael@smithvalley.com.
You do not need to know all this to use the code, but if you are curious here are the issues:
First, setting rendering hints requires a reference to a class the Microsoft VM does not know about. When the class is loaded the MS VM throws an exception. Normally you would case out this code and simply not call the alien method if java.version reports that the VM does not support it, but still it throws an exception. This is because the JIT (just-in-time compiler) hits ALL the byte-code including the code on either side of your IF statement which includes the reference to your alien class.
Second, you cannot use reflection in an applet without throwing a security exception. The argument for why they do this is that it could allow "evil doers" to write applets that refers to a class which is somehow placed in the classpath through some back door.
The solution presented here moves the alien method call to a special static class (AntiAliasEnabler) which makes the alien method call within a try-catch block. Then your code calls AntiAliasEnabler.setAntiAlias() instead of making the call directly. This enables the JIT to compile your code because the call is no longer to an alien class, AntiAliasEnabler is a known object. Later when the code is actually running it makes the call, AntiAliasEnabler catches the exception and sets a boolean so that it does not try to do that again. Subsequent calls to set rendering hints will see the boolean is set and simply return without going through the overhead of throwing an exception each time.
But the story doesn't end here. I was calling AntiAliasEnabler.setAntiAlias() to draw high quality text and everything was fine. When I added a second call to AntiAliasEnabler.setAntiAlias() to anti-alias the rounded rectangle it failed with a class not found exception. It could not find the AntiAliasEnabler class. Apparently the JIT remembers that when it tried to compile AntiAliasEnabler it threw an exception and then it holds a grudge. Any other calls from a different location invoke the JIT, the JIT sees that it got an exception the last time it tried to compile this class and throws a class not found exception. The first call still works (presumably) because the JIT threw an exception, I caught it and set a Boolean so it does not try that again and enough compiled code seems to have been left behind to run again without a problem (try not to think about it too much).
The solution to this final problem was to add yet another level to the calling layers. If I create a static method in my main class which calls AntiAliasEnabler.setAntiAlias(), then bottleneck all my calls through the main class everything works fine. The JIT compiles the link to AntiAliasEnabler.setAntiAlias() through my main class the first time it is called and after that I can call that method through my main class from anywhere in the applet and the compiled code passes me right on through, it doesn't try to invoke the JIT again.
This works on the Windows XP VM (as of 6/14/04) and the VM on Windows 2000 containing the latest updates. I don't know about other VM's (Windows 95, 98, etc). I would not put this in production code until it had more testing. It is a bit of a hack but the MS VM is static (except for security fixes). If a hack works now it is likely to work in the future, except for one little thing...
If Microsoft does not allow refection in applets because it gives "evil doers" as way of calling alien classes, what is different about this? Is this not just another way to call alien classes? Is this a time-limited solution, a security hole waiting to be plugged?
This is a concern but I don't think it will be a problem. The Java to .NET converter already stubs out references to objects it does not know about in one swoop when it converts Java byte-code to an assembly. Since Sun and Microsoft buried the hatchet we can expect to see Java applets running directly on .NET. When that happens the JIT will be in a Java sandbox while it converts the Java byte-code to IL and references to alien classes will be stubbed out harmlessly. Any interim fixes to the current VM are likely to follow that path rather than break existing applets and so far they are showing great care in being backward compatible in this early Java-to-.NET stuff. So in summary, it may be they will "fix" this but it is not likely the fix will break us.
Mike Smith