Mike on the MATLAB Desktop
July 6th, 2009
Calling Java from MATLAB
So far no one has taken me up on the extra credit from the Interactive Web Pages post. I thought the problem of displaying a figure without an image file was too interesting to pass up, so I figured out the solution myself and put it up on the file exchange. The second challenge involving ActiveX will remain open until I get chance to write up its solution. Or, if you don't have the time to do that, you can still win a t-shirt by sending us your desktop.
My solution to the image challenge involves encoding binary information from an image file as text through the base64 scheme. At first I thought to implement the base64 algorithm myself in MATLAB, but I learned my lesson the hard way a few years ago writing my own md5 hash-computing program (don't ask). This time I wanted to use a readily-available solution. Since there is no toolbox function for this, I decided to take advantage of a Java library since (a) I could use the same library on every platform (instead of needing a different pre-compiled binary) and (b) I am pretty comfortable with Java. My solution takes advantage of the freely available Apache Commons Codec package.
Using Java from a MATLAB program is as simple as using a MATLAB function, particularly if you are used to using MATLAB package functions. You can use any public method in the Java SE API from the command line. The running version of the JRE depends on your version of MATLAB and operating system and determines what API functionality is available from MATLAB. To determine the Java version use the command version('-java'). To change the Java version (not recommended) you can follow these instructions.
For instance instead of MATLAB's str2num you could use: Double's parseDouble.
str2num('2.3')
java.lang.Double.parseDouble('2.3')
ans =
2.3000
ans =
2.3000
Of course, this is a trivial example. Many of our functions such as xmlread make use of more complicated series of calls to java objects. The payoff in the sendmail function comes at the end using the Transport object to send a pre-constructed MimeMessage.
javax.mail.Transport.send(msg)
My base64 program does not use a class from the standard JRE (in fact, neither does sendmail) but instead uses a third party library (Apache Commons Codec) that I happen to know ships with MATLAB and is already available on the classpath.
encoder = org.apache.commons.codec.binary.Base64;
base64string = char(encoder.encode(bytes))';
These examples has three things about using Java that I want to address so you can use other Java libraries in MATLAB: (1) the class path, (2) calling syntax, and (3) data types.
Java Class Path
MATLAB maintains a path for Java classes separate from the search path. That means even if you have a .class or .jar file on the MATLAB path, unless you use javaaddpath you will not be able to use it. To see what is currently on the path use javaclasspath. Running this command you will show you a long list of files that ship with matlab called the Static Class Path and then you'll see the Dynamic Class Path. The dynamic class path is where classes added to the path with javaaddpath will be placed. They can be removed with javarmpath and have to actively reloaded each session of matlab. The static class path comes from $matlabroot\toolbox\local\classpath.txt and are only added to the class path at MATLAB startup. The ones listed here by default are all the Java classes we write (everything in the com.mathworks package). Calling any of these classes directly is not supported and likely to break on a release-to-release basis, but there are resources on the web that make use of these effectively.
Calling Java Functions
Once you add a class to the classpath and it shows up in the javaclasspath, you can use it from the Command Line or from a MATLAB-file. To do that you can use the fully-qualified name (e.g. javax.swing.JTable) or like with MATLAB packages, you can use the import statement to just call the class name (e.g. import('javax.swing.*'),JTable ).
Data Types
Looking at my string to double example you'll see that I passed a MATLAB char array to the java function and got back a MATLAB double, even though methodsview('java.lang.Double') shows that parseDouble takes a java.lang.String as its input. MATLAB will automatically convert primitive types when calling Java methods, as well as convert char arrays to java.lang.String objects when used as inputs. As you can see in my base64 example, I have to explicitly convert the java.lang.String returned by encoder.encode() to a MATLAB char array.
Those are the basics of calling Java. In future posts I hope to discuss memory management with Java (a topic of some recent technical support queries) as well as threading issues, as related to GUIs.
By
Michael Katz
Mike is a developer on the MATLAB Desktop team. When not describing himself in the third person, biking, homebrewing, or rooting for the home team, he's busy trying to make the world a better place for programming.
11:33 UTC |
Posted in java |
Permalink |
You can follow any responses to this entry through the RSS 2.0 feed.
You can skip to the end and leave a response. Pinging is currently not allowed.
Leave a Reply
|
I think calling java from matlab is one of the most useful capabilities of the whole system. Adding support for all swing components to guide would be simply awesome.
We’re certainly working on a nice, easy way to do this. However there are a several not so nice ways, maybe a future article here…
With the COM external interface one can register a matlab listener for COM events. Is the equivalent possible for Java? I can’t seem to find anything in the help files.
Dora,
It depends on what events you want to listen for. For instance, you can set MATLAB functions as AWT listeners:
f = javax.swing.JFrame; set(f,‘ComponentResizedCallback’, @(handle,evt) disp(evt.getSource.getSize)); f.setSize(200,200); f.show;I think I will cover this stuff in a future post.
Hi Ken and Mike,
I received a simulation program written by someone and he asked my help to connect his simulation into matlab. SO he can use matlab function to start and stop the simulation.
Since you both are expert, I would like to ask you something about this.
To run the simulation there is a file “main” which is written in Windows NT command script (that’s what written in the file property), and to change the parameters of the simulation, he can write a java-script file and call it via “main” file.
I am not familiar with java, nor with the NT command script, and I can not see what is inside the “main” file. Therefore, do you have any suggestion how to put the “main” file I described above into m-file?
So the “main” file can be run under matlab functions.
sorry if I misaddress this question.
Any response will be appreciated,
best,
-bree
I have a problem in that the Java “JMSL” classes I’m trying to call from MATLAB are commercial and license protected. We have a filebased license and it works from normal java by passing the path to the JVM via the “-D” option.
So I tried to tell the MATLAB JVM where the license file was via the setProperty java method This is how I tried to tell JVM about the file:
javaMethod(’setProperty’, ‘com.imsl.license.path’, ‘D:\dir1\dir2\license.dat’);
I put this at the top of the m file hoping that
the javaMethod, javaObject and javaArray calls I made
after that would then be satisfied by finding the license.
I get an error that the license server could not be found
Mark
Mark - try placing the -D directive in the java.opts file, as explained here: http://www.mathworks.com/support/solutions/en/data/1-18I2C/?solution=1-18I2C
Yair
Thanks for that reply, Yair. MATLAB passes the contents of java.opts to the Java VM as command-line parameters at startup.
Hi
First of all, thanks for the post, it is really useful. I am trying to develop a Java GUI within Matlab and I want to include the log4j API to control logging or tracing of the application.
I followed the steps how this post says. I put the log4j.jar into classpath.txt and it appeared on the list of .jar files when I executed javaclasspath. After that I called (e.g. javax.log4j.Logger) or (e.g. import(’javax.log4j.*’), Logger ) but it didn’t work.
So if you could help me I’d appreciate it. If I manage to develop an interesting application including log4j API, I don’t mind to share with everyone.
Kind Regards,
Jose Miguel
Jose,
You need to make sure you are using the right class names and method signatures. Unlike MATLAB, Java is not forgiving when it comes to using the right inputs since it is statically typed.
You can create a log4j object with the following code:
See the log4j documentation for more information. We won’t be able to help you use these classes. For help you should post questions in the Apache forums or on the MATLAB newsgroup.
Hi Mike,
I have a problem. I wrote .m file that calls Java classes that are provided to control a hardware. The program is working. But, I would like compile the program so that I can deploy in a different computer. But, the compiled program is not able to execute the commands. The target system has the java classes installed, I updated ‘classpath.txt’ and ‘librarypath.txt’ in the /…/local folder. I tried to find more information on Java code in the .m file and problems with compilation. I appreciate your input.
Sincerely,
Ravi.
Ravi, What you described should work as far I understand it. Please follow up with technical support. With a little more information they should be able to help you straighten it out. http://www.mathworks.com/support/service_requests/contact_support.do
Please, could you help me how call from m-file throught java code simulink mdl scheme ? Thanks a lot
@Pavwell,
Your question does not make sense. This article is about using Java classes from MATLAB programs. There are blocks in Simulink that allow you to run MATLAB commands, which you can use these techniques from there, although I doubt the model would compile to C-code.
My problem is : I have mdl simulink scheme with real system. And my task is to use Java to run simulation of this simulink scheme. And because of it and want to do this from m-file because i want to use this m-file by Java Builder to create jar file for web based java application.
Pavwell,
It’s been awhile since I last handled stuff related to the MATLAB Compiler and Java Builder, but I don’t think you can compile and deploy a MATLAB application that runs a Simulink model: See http://www.mathworks.com/products/compiler/compiler_support.html and http://www.mathworks.com/access/helpdesk/help/toolbox/compiler/br2cqa0-20.html.
If you have real-time workshop, you can compile a Simulink model to C code. Then you can package it in a libray and call it through JNI. It’s a bit complicated to do that, though.
What if i would like to call a matlab function from a jar executable outside MATLAB?
Would the same methodology as described in matlab help work?
Dimitris,
Without a MATLAB, you’ll need to use MATLAB Builder JA to deploy MATLAB code for use with java.
Hi Mike
what is the com.mathworks package? where i can read more about objects and classes of this package?
@Amin,
com.mathworks.* represent Java classes that we’ve built here. These mostly represent the libraries and widgets used by the Desktop and toolboxes, and as such are not considered part of the MATLAB language and are largely documented. Occasionally we mention some of these in technical support solutions as workarounds to bug fixes. Some of the classes are documented for use for xml, web, and database I/O, and a whole bunch are meant for use in with the MATLAB Builder JA product for deploying MATLAB code to work with Java programs.