Tricks of the Trade
In and Out
Download This Issue
Building User Interfaces Using J/Link
In this section we will examine the basic concepts of J/Link programming. My intent is to cover just enough for readers to become comfortable with the user interface examples developed later. I will make occasional references to specific sections in the J/Link User Guide. These references will be given as section numbers, and you can use these section numbers in the Go To field of the Help Browser. If a reference is to Section 1.2.1, for example, you can type “J/Link 1.2.1” (without the quotation marks) in the text field at the top and click the Go To button. You must make sure that the Add-ons button is depressed when you do this, as the User Guide is in the Add-ons section of the Help Browser. If you are reading this article as a notebook, then of course you can just click the links and be taken to the appropriate pages in the Help Browser automatically.
What is J/Link?
J/Link is a toolkit that integrates Mathematica and Java. It lets you call Java from Mathematica and Mathematica from Java. It sits on top of MathLink, Wolfram Research’s protocol for communicating with the Mathematica kernel. When you use J/Link to call Mathematica from a Java program, you can think of it as a MathLink Developer Kit for Java. When you use it to call Java from Mathematica, as in this article, it is just a Mathematica package that provides functionality for launching and controlling a Java runtime. You simply load the package and start writing programs that use it. The internals of J/Link are written in a combination of Mathematica, Java, and C. All the source code is provided for those who might be interested, and can be found in <Mathematica /AddOns/JLink/Source and <Mathematica directory>/AddOns/JLink/Kernel (where the Mathematica code resides).
Beginning with Mathematica 4.2, J/Link is a standard part of the Mathematica system, not an add-on that you or your users need to download and install (although this is necessary in Mathematica 4.0 and 4.1). A Java Runtime Environment is also installed with Mathematica 4.2, so J/Link is ready to use right out of the box. This means that you can write J/Link programs for others and know that they will work without any setup on the user’s part. They might be completely unaware that Java is even being used. Those with Mathematica 4.0 and 4.1 need to install J/Link and a Java Runtime Environment on their own, although many people will already have an appropriate Java system on their machines. J/Link includes installation instructions and information on obtaining a Java runtime for those with Mathematica 4.0 and 4.1. The current version of J/Link is 2.0, and that is the version assumed for this article. The home page for J/Link is www.wolfram.com/solutions/mathlink/jlink.
Starting the Java Runtime
The first step in using J/Link is to load the package.
Java programs execute in a managed environment called a Java Runtime Environment, or just a “Java runtime.” Before you can use J/Link from Mathematica, you must launch the Java runtime. All calls from Mathematica into Java are directed to this single Java runtime, which runs as a separate process from the Mathematica kernel. MathLink is used to communicate between the kernel and the Java runtime, but you do not have to be concerned with such details.
The function that launches Java is called InstallJava, named after the existing Mathematica function Install, which launches an external program and prepares it to be used via MathLink.
J/Link also has functions for shutting down the Java runtime (UninstallJava) and for restarting it (ReinstallJava). Do not use them. Developers need to remember that the Java runtime used by J/Link is a shared resource. Other Mathematica packages you have loaded might also be using J/Link, and shutting down Java will cause problems for them. Start the Java runtime when you need it and then just leave it running.
If Java is already running when you call InstallJava, the function does nothing. This means that it is safe to call it whenever you want, such as at the start of any programs that need J/Link.
Creating Objects and Calling Methods
Now let us begin calling into Java. An obvious first step is to create a Java object. In Java, you use the new operator for this. In Mathematica, you use the JavaNew function. Here we create an object of the Date class.
The first argument to JavaNew is the full name of the class with all the periods. Any arguments to the constructor would be given in a sequence after the class name, but the constructor being invoked here takes no arguments. It creates a Date object that represents the current time. Note that the return value is a funny expression surrounded by angle brackets. The angle brackets remind you that this is a special output form, not the true Mathematica representation of the expression. A JavaObject expression, as this is called, is a Mathematica representation of a Java object that lives in the Java runtime.
How did I know the name of the class and the arguments to the constructor I wanted to invoke? Obviously, I read the Java documentation. To use J/Link you are not going to have to learn the Java language, but you will have to learn what Java classes are available and what methods they contain. There are many books describing the standard Java class libraries, and for some uses you can get by with just the so-called “JavaDoc” help files. JavaDoc is a hyperlinked web page format for supplying help files for Java classes. A complete JavaDoc reference to the standard Java class libraries (including the user interface classes) can be found at java.sun.com/j2se/1.4/docs/api.
If you look at the documentation for the java.util.Date class, you will see that it has a method called toString() (all Java objects have this method). Here is how to call the toString() method.
If you are familiar with Java, you would know that to call this method you would write in Java:
It looks almost the same in Mathematica except that we use the @ symbol instead of the dot, and we use square brackets instead of parentheses. Throughout J/Link, we use the @ like Java’s dot, to mean “call this method (or access this field) on the preceding object.” Below is a table taken from Section 1.1.6 of the User Guide that compares the Mathematica and Java syntaxes for all the different ways you use Java objects.
If this chart is hard to understand or the Mathematica syntax looks unfamiliar, do not worry. After just a few minutes of writing J/Link code yourself, it will become very natural.
We have already seen an example of how to call a method on an object (a so-called “instance” method). Classes can also have static methods and fields, which are associated with the class itself and not any specific object of that class. For example, Java has a class called Math that contains a number of mathematical functions like abs(), sqrt(), sin(), and so on. You do not ever create an object of type Math and call methods on it. It is just a container for a collection of static methods that operate on numbers.
To call a static method, the first thing you must do is load the class into Mathematica. Any Java class you use with J/Link must be loaded into Mathematica, but this happens automatically for you when you call JavaNew to create the first object of that class. When calling a static method, however, you are not using an object of that class, so the class might not have been loaded yet. You have to do it manually using LoadJavaClass.
When you call a static method you use the class name as a prefix, separated from the method name by a context mark.
You will note that static methods and fields are the exception to the rule that dots in Java become @ in Mathematica. Although this sometimes causes confusion for novice J/Link programmers, it is actually quite natural. Java uses the dot in two very different ways—as the member access operator, as in obj.method(), and as the scope resolution operator, as in package.Class.staticMethod(). Some other object-oriented languages use different operators for these two meanings (C++ uses :: as the scope resolution operator). Although it is not often described in this way, the context mark is Mathematica’s scope resolution operator. In other words, do not complain that Mathematica requires two different operators, complain that Java overloads the dot for two very different meanings.
J/Link maps Java types to their natural equivalents in Mathematica. For example Java integer types (char, int, long, and so on) map to Mathematica integers. Arrays in Java map to Mathematica lists of the appropriate depth. Java objects map to JavaObject expressions. When I say “map,” I mean that if a Java method takes an int, then you call it from Mathematica with an integer argument. If a Java method returns an int, you will get an integer in Mathematica as the return value. Section 1.1.4 of the User Guide has a table showing the complete set of type mappings. It should correspond with most people’s intuition about which types are most logically equivalent (for example, boolean maps to True or False in Mathematica, and the null object maps to Mathematica’s symbol Null).
Underscores in Java Names
Some Java names have underscores (_) in them. These characters are especially common in the names of constants, for example TOP_ALIGNMENT. This causes a problem for J/Link because the underscore is not a valid character in a Mathematica symbol name. J/Link solves this problem by mapping the underscore into a capital U in symbol names. The rule is that when you use a Java name in a Mathematica symbol, you convert the _ to a U, but when you use the name in a Mathematica string, you do no conversion (in other words, you convert only when necessary). For example, if you have a class named My_Class with a field named SOME_CONSTANT, you would get the value of that field like this.
But when you refer to the class name in a string, you keep it unmodified.
Cleaning up Unused Objects
J/Link keeps track of which Java objects have been sent to Mathematica so that it can prevent the Java garbage collector from trying to free them while they are still in use by Mathematica. Unless you explicitly tell J/Link that you are finished with a Java object in Mathematica, it will never allow the object to be freed and objects will pile up in your Java session. This is generally not a problem if you are just tinkering with J/Link, but, in code that you write for others to use, you should make sure that you clean up any Java objects that are no longer needed.
You use the function ReleaseJavaObject to tell J/Link that you no longer wish to use a Java object in Mathematica. Here we release the Date object we created earlier.
It is an error to refer to an object in Mathematica after it has been released.
In actual practice, ReleaseJavaObject is not used very often because it is too much effort to keep track of every object sent to Mathematica. What you usually want is a way to create a block of code in which all newly-created Java objects will be marked as temporary and automatically released when the block finishes. This is especially the case with user interface programs—your program will create a window with some controls in it and display it to the user, but, when the user closes the window, the program is done and does not need to leave anything behind. In the same way that any local variables that were used get cleaned up, you want any Java objects sent to Mathematica to be released. The function that accomplishes this is JavaBlock.
Many J/Link programs will have the following structure.
You can be guaranteed that MyFunc will not “leak” any objects, meaning that any objects sent to Mathematica for the first time during the execution of MyFunc will be released when it finishes. Note that only objects sent to Mathematica for the first time will be released. Objects that have already been seen by Mathematica will not be affected. This means that you do not have to worry that JavaBlock will aggressively release an object that is not truly temporary to that evaluation.
Remember that Java objects are sent to Mathematica not just when you call JavaNew, but also when you call a Java method that returns an object. You might not even have assigned the object to a variable, such as when you chain method calls.
In this example, methodThatReturnsObject() will cause a JavaObject expression to be created in Mathematica but not be assigned to any variable. This is why you should get in the habit of wrapping JavaBlock around code that does not need to create long-lived Java objects in Mathematica. You cannot tell whether a program creates objects in Mathematica simply by looking for calls to JavaNew.
There is one useful exception to the rule that all novel objects encountered during a JavaBlock are released when it ends. If a JavaBlock returns a single object, that object will not be released. This allows another common programming pattern in which you create several objects and operate on them, but you need just one of them to live beyond the boundary of the JavaBlock. We will see examples of this later, such as when you create a Frame object and populate it with controls (which are themselves objects), but you need the Frame object itself to persist after the function that created it finishes.
Getting Information about Classes
J/Link provides a few utility functions that let you see what constructors, methods, and fields a class includes. Although this is no substitute for documentation on the classes you are using, it can be very useful as a quick help system. Here we inspect the constructors for the java.awt.Button class.
Here are the fields.
There are a lot of methods in the Button class, the vast majority of which are inherited from parent classes (especially the very large class java.awt.Component). If you are only interested in the methods unique to the Button class, you can use the option Inherited->False.
You can also use string patterns to restrict the members you want to see. Here we specify that we only want to see the “set” methods (because we have left out the Inherited->False option, we see many methods defined in parent classes).
The examples above used the class name as the first argument, but you can also use an object of the class.
About Mathematica Download Mathematica Player
Copyright © 2003 Wolfram Media, Inc. All rights reserved.