JMI – Java-to-Matlab Interface

I would like to welcome guest writer Joshua Kaplan, an expert in one of the darkest undocumented corners of Matlab – that of the Java-to-Matlab interface (JMI). Today, Joshua will introduce JMI and its core functionality. Later articles will explore additional aspects of this complex technology.

As you’ve seen many times on this blog before, Matlab can easily call Java. This article explores the dark undocumented territory known as JMI (Java Matlab Interface) that enables calling Matlab from Java. This interface takes the form of a file called jmi.jar that comes with every copy of Matlab released in the past decade. JAR files are essentially a zip file containing Java class files. In this case, several Java classes in jmi.jar enable interaction with Matlab. This post will discuss the most important class: com.mathworks.jmi.Matlab.

Matlab’s dynamic evaluation functions

JMI easily allows calling two built-in Matlab functions: eval and feval. Essentially, eval evaluates any string typed into Matlab’s Command Window, and feval allows calling any function by name and passing in arguments. For example:

>> sqrt(5)
ans =
    2.2361
>> eval('sqrt(5)')
ans =
    2.2361
>> feval('sqrt',5)
ans =
    2.2361

The first approach takes the square root of 5 normally by directly calling Matlab’s square root function sqrt. JMI does not enable this direct-invocation approach. Instead, JMI uses the second approach, where eval mimics the first call by evaluating the entire expression inside single quotes. The third option, also used by JMI, is to use feval where the function and arguments are specified separately. While in the above example calling eval and feval is very similar, there are differences. For instance, assignment can be done as x=5 or eval(‘x=5’) but there is no feval equivalent. There are also other eval relatives, such as hgfeval, evalc and evalin, which will not be explained today.

Before we explore com.mathworks.jmi.Matlab, it is important to note a few things: Everything that follows is based on many hours of experimentation and online research and so while I am more or less certain of what I am about to explain, it could be deficient or incorrect in many respects. In fact, this area is so undocumented that an article written in 2002 by one of The MathWorks employees and published in the official newsletter, has been removed from their website a year or two ago.

Secondly, this post is written to satisfy people’s curiosities regarding JMI. If you actually wish to call Matlab from Java, I strongly suggest you use MatlabControl, a user-friendly Java library I have written that wraps JMI. There are many complications that arise with threading, method completion blocking, virtual machine restrictions, and other domains that prevent using JMI directly to be practical and reliable.

com.mathworks.jmi.Matlab class and its mtEval() method

With all of that said, let’s dive in! In the Matlab Command Window type:

methodsview('com.mathworks.jmi.Matlab')

You will see all of the Matlab class’s numerous methods. Many of the methods have extremely similar names; many others have the same names and just different parameters. In order to call eval and feval we are going to use two of Matlab‘s methods:

public static Object mtEval(String command, int returnCount)
public static Object mtFeval(String functionName, Object[] args, int returnCount)

Since Matlab can call Java, we can experiment with these methods from Matlab. That’s right, we’re about to use Matlab to call Java to call Matlab!

First, let’s import the Java package that contains the Matlab class, to reduce typing:

import com.mathworks.jmi.*

Now let’s take the square root of 5 like we did above, but this time from Java. Using JMI’s eval-equivalent:

Matlab.mtEval('sqrt(5)',1)

Here, ‘sqrt(5)’ is what will be passed to eval, and 1 signifies that Matlab should expect one value to be returned. It is important that the second argument be accurate. If instead the call had been:

Matlab.mtEval('sqrt(5)',0)

Then an empty string (”) will be returned. If instead, 2 or more were passed in:

Matlab.mtEval('sqrt(5)',2)

Then a Java exception like the one below will occur:

??? Java exception occurred:
com.mathworks.jmi.MatlabException: Error using ==> sqrt
Too many output arguments.
    at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method)
    at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:212)
    at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121)
    at com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1478)
    at com.mathworks.jmi.Matlab.mtEval(Matlab.java:1439)

Looking at this exception’s stack trace we notice that mtEval() is actually internally calling mtFeval().

com.mathworks.jmi.Matlab class’s mtFeval() method

Now to perform the square root using JMI’s feval-equivalent:

Matlab.mtFeval('sqrt',5,1)

Here, ‘sqrt’ is the name of the Matlab function to be called, 5 is the argument to the function, and 1 is the expected number of return values. Again, the number of return values. If this number is specified as 0 instead of 1, the function call will still succeed, although not all of the results will necessarily be returned. The second mtFeval() argument, which specifies the arguments to the invoked Matlab function, can take any number of arguments as an array. Therefore the following is acceptable:

Matlab.mtFeval('sqrt',[5 3],1)

This will return an array containing both of their square roots. Note that although two vales are returned, they are considered as only 1 since it is a single array that is returned.

Multiple Matlab arguments can be specified in mtFeval() using a cell array. For example, consider the following equivalent formats (note the different returned array orientation):

>> min(1:4,2)
ans =
     1     2     2     2
>> Matlab.mtFeval('min',{1:4,2},1)
ans =
     1
     2
     2
     2

As we observed above, mtEval() is really just calling mtFeval(). This works because eval is a function, so feval can call it. An illustration:

Matlab.mtFeval('eval','sqrt(5)',1)

com.mathworks.jmi.Matlab class’s mtFevalConsoleOutput() method

Both mtFeval() and mtEval() have allowed us to interact with Matlab, but the effects are not shown in the Command Window. There is a method that will allow us to do this:

public static Object mtFevalConsoleOutput(String functionName, Object[] args, int returnCount)

mtFevalConsoleOutput() is just liked the mtFeval() command except that its effects will be shown. For instance:

>> Matlab.mtFeval('disp','hi',0);  % no visible output
>> Matlab.mtFevalConsoleOutput('disp','hi',0);
hi

There is no equivalent mtEvalConsoleOutput() method, but that’s not a problem because we have seen that eval can be accomplished using feval:

>> Matlab.mtFevalConsoleOutput('eval','x=5',0);
x =
     5

Other methods in com.mathworks.jmi.Matlab

There are many more eval and feval methods in the Matlab class. Most of these methods’ names begin with eval or feval instead of mtEval and mtFeval. Many of these methods are asynchronous, which means their effect on Matlab can occur after the method call returns. This is often problematic because if one method call creates a variable which is then used by the next call, there is no guarantee that the first call has completed (or even begun) by the time the second call tries to use the new variable. Unlike mtEval() and mtFeval(), these methods are not static, meaning we must have an instance of the Java class Matlab:

>> proxy = Matlab
proxy =
com.mathworks.jmi.Matlab@1faf67f0

Using this instance we will attempt to assign a variable and then retrieve it into a different variable. The result will be a Java exception indicating that ‘a’ does not currently exist:

>> proxy.evalConsoleOutput('a=5'); b = proxy.mtEval('a',1)
??? Java exception occurred:
com.mathworks.jmi.MatlabException: Error using ==> eval
Undefined function or variable 'a'.
    at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method)
    at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:212)
    at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121)
    at com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1478)
    at com.mathworks.jmi.Matlab.mtEval(Matlab.java:1439)
a =
     5

If you run the above code you are not guaranteed to get that exception because of the nature of asynchronous method calls. However, this inherent unpredictability makes it difficult to perform almost any sequential action. Therefore, it is best to stick to mtEval, mtFeval, and mtFevalConsoleOutput, where this type of exception will be very remote. (They can still occur, about 1 in 100 times, as to why – I’d love to know as well.)

Two particular methods that may come in handy are mtSet() and mtGet(), which are the Java proxies for the Matlab set and get functions – they accept a Matlab handle (a double value) and a property name (a string) and either set the value or return it. Like Matlab, they also accept an array of property names. This can be used to update Matlab HG handles from within Java code, without needing to pass through an intermediary Matlab eval function:

>> Matlab.mtSet(gcf,'Color','b')
>> Matlab.mtGet(gcf,'Color')
ans =
     0
     0
     1
>> Matlab.mtGet(gcf,{'Color','Name'})
ans =
java.lang.Object[]:
    [3x1 double]
    'My figure'

Summary

With just eval and feval, an enormous amount of Matlab’s functionality can be accessed from Java. For instance, this allows for creating sophisticated Java GUIs with Swing and then being able to call Matlab code when the user clicks a button or moves a slider.

My next post will be on using MatlabControl to control Matlab from Java from within Matlab. The following post will discuss doing the same, but from a Java program launched outside of Matlab.

Related posts:

  1. Matlab-Java interface using a static control The switchyard function design pattern can be very useful when setting Matlab callbacks to Java GUI controls. This article explains why and how....
  2. Matclipse – Eclipse-Matlab interface Matclipse is an open-source plugin for the popular Eclipse IDE that connects it with Matlab. ...
  3. Matlab-Latex interface Matlab's support for Latex has some hidden quirks ...
  4. Java stack traces in Matlab Matlab does not normally provide information about the Java calls on the stack trace. A simple trick can show us this information....
  5. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
  6. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....

Categories: Guest bloggers, High risk of breaking in future versions, Java, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

13 Responses to JMI – Java-to-Matlab Interface

  1. Pingback: Tweets that mention JMI - Java-to-Matlab Interface | Undocumented Matlab -- Topsy.com

  2. Lior says:

    Very useful post. Thank you very much.

    I am trying to use jmi to run a large java project from within matlab and I keep running into problems regarding PermGen space
    “java.lang.OutOfMemoryError: PermGen space”

    Increasing the maximum jvm memory helps to some extent, however, I cannot find a way to directly increase the PermGen space.

    Any advice?

    Thank you,

    Lior

  3. Jeet says:

    I need to call the eig() function of Matlab from my Java program….how exactly do I do this??

  4. Pingback: MATLAB | Thermal Vision Research

  5. shantanu says:

    Hi,

    Thanks for that very nice post. I am just wondering, is it possible to use Java multi-agent based framework (JADE) with MATLAB/Simulink using JMI? Have anyone done this? Please share me some ideas.

    Thanks

  6. Vincenzo says:

    Thanks. This was very useful for me. I searched a solution for about 2 months. Now i have the solution.
    You are Great!!!

  7. Baba says:

    Hi,

    Thanks for the post. I need to call a Matlab script with input arguments of different types (large matrices of different sizes) through Matlab.mtFevalConsoleOutput. Also, the Matlab script accepts only double matrices, not cell arrays. Can you please advise?

  8. Pingback: Explicit multi-threading in Matlab – part 1 | Undocumented Matlab

  9. Ramlal Chaudhari says:

    I need to call the main() function of Matlab and pass one input image to that main function from my Java program.
    And how I can Exactly do that in proper manner..??
    If someone know, please help me….

Leave a Reply

Your email address will not be published. Required fields are marked *

*

<pre lang="matlab">
a = magic(3);
sum(a)
</pre>