Matlab comes pre-bundled with a vast number of Java classes that are available for immediate
use in any Matlab program, as we have seen above However, it is sometimes useful to
have a user-created Java class Such classes may be an extension of an existing class with some
functionality, or perhaps an entirely new class
Matlab runs directly from the source m-files, creating the executable code on-the-fly
Java, on the other hand, needs a compiled (class) file to run and cannot run directly from the
source ( java) file When we use any of the Matlab-bundled Java classes mentioned
above, we are actually using a precompiled class file, the source code for which is not
available For our user-created classes, we need to compile our source files into similar
class files
We have two options for compiling user classes: we can either use a standalone Java compiler
or use an integrated Java development environment (IDE)
there are many Java compilers, but the simplest is probably the javac compiler, which is
part of the official Java Development Kit (JDK), which can be downloaded from http://java
sun com/javase/downloads/previous jsp and used freely While doing so, ensure to use a JVM
version not newer than the one used by the Matlab version, as reported by the “version
-java” command in the Matlab desktop (see details in Section 1 8) For example, if our
application is meant to target Matlab R2007a (7 4), which uses JVM 1 5, then we should
be careful to compile using JDK 1 5 rather than the latest version (1 6) 36 In practice, JVM 1 5 provides almost all the functionalities of 1 6, while enabling backward compatibility with
all Matlab releases since 2005 (R14 SP2 a k a 7 0 4) to provide earlier backward compatibility,
you will need to use JDK 1 4 2 or even 1 3, but these JDKs lack important Java functionality
(e g , Generics) In summary, I suggest to normally compile with JVM 1 5, except
in rare cases
to use the javac compiler, simply run “javac MyJavaClass.java” from the operating
system’s command line, replacing “MyJavaClass” with the actual name of the class If the
class uses some other classes, indicate their classpath location using the –cp command-line
switch If the source code has errors, they will be reported Otherwise, we will get a file called
MyJavaClass.class which should now be placed in Matlab’s dynamic or static Java classpath
(see Section 1 1)
Note: Java classes must be placed in files that are named exactly like their contained class
So, class MyJavaClass must be placed in MyJavaClass.java a much preferred alternative to javac is to use a Java IDE there are several excellent free
and commercial IDEs two of the best free IDEs are Eclipse37 and Netbeans38 (some other
popular Java IDEs are Jbuilder, IntelliJ, and JDeveloper, but I will only discuss Eclipse and
Netbeans below) there is an active “religious war” among developers regarding which of
these IDEs is better In all IDEs, compilation is done on the fly, and errors are visually displayed
next to their offending source It is also easy to modify the compiler to use an earlier
JDK, a need that was explained above †
Once the class file is generated, we need to place it in Matlab’s Java classpath, as explained
in Section 1 1 this can be done either dynamically (using javaaddpath or javaclasspath),
statically by adding the class path-name to the classpath.txt file (which(‘classpath.txt’)), or by
adding the class file to one of the classpath folders
Java classes are not reloaded automatically by Matlab, when recompiled outside
Matlab to reload a modified Java class, we need to restart the JVM by restarting Matlab
For classes placed on the dynamic classpath, you can try Matlab’s clear(‘java’) command,
while remembering its side effect of clearing all globals However, this does not always work
(e g , if the class signature has changed)
Expert Java programmers can try to use Paul Milenkovic’s suggestion39 for a proxy classloader,
as an alternative to restarting Matlab or clearing Java as Dan Spielman explains,40
“the rough idea is that you create a classloader for your class, and then access it through the classloader after you recompile, you kill the classloader and then create a new instance of it,
which then reads the recompiled class” †
In practice, I suggest restarting Matlab after Java classes are recompiled, even when this
is not strictly necessary It may save a lot of frustrating debugging and chasing down errors that
only happen because Matlab keeps an old class in memory
this brings us to the issue of debugging When using user-created Java classes in Matlab,
we often need to debug the Java code there are many online resources for debugging
Java code 41 a general advice when creating such Java classes is to remember to set public
visibility to all Java elements (fields/methods/classes) that need to be visible in Matlab, otherwise
we will encounter hard-to debug problems 42
Unfortunately, Matlab’s built-in debugger can only debug the Matlab code, stepping
over Java invocations there are two basic approaches for debugging the Java code:
the simplest way is to add debug printouts within the Java code these printouts will be
displayed on the Java console, which in Matlab JVM’s case is redirected to the Matlab
Command Window It is ugly but it works:
public int myMethod(int row, int column, double value) {
System.out.println(row + "," + column + "=> value: " + value);
// do something useful here...
}
the down-side to this approach is that whenever printouts should be modified or removed,
the Java code needs to be recompiled
a slight improvement of this stone-age debugging is to include a debug flag that can be
turned on/off at will the drawback is that, while preventing the need for recompilation, the
compiled class remains unnecessarily bloated even after all the development debugging has
ended and the debugging framework is no longer needed:
public class MyClass
{
private boolean _debug = false;
public void setDebug(boolean flag) {
_debug = flag;
}
public int myMethod(int row, int column, double value) {
if (_debug) {
System.out.println(row + "," + column + "=> " + value);
}
// do something useful here. . .
}
}
a significantly more powerful method of debugging entails step-by-step debugging using a
Java integrated debugger/editor (IDE) a very simple and useful trick is to add a public
static main method to the Java class, thereby enabling it to run (and be debugged) as a
standalone Java application in the Java IDE Once you have fully debugged the class in the Java
IDE, it can be used in Matlab
to connect the Java IDE to a running Matlab, simply start Matlab with the jdb (Java
debugger) flag and then connect the Java debugger to the Matlab process via default port
4444, as described by brad Phelan:43
matlab -jdb
Matlab will now display the following message when it starts:
JVM is being started with debugging enabled.
Use "jdb -connect com.sun.jdi.Socketattach:port = 4444" to attach debugger.
Note that the –jdb flag is incompatible with some other startup flags (e g , -nojvm and -nosplash)
Matlab may fail to start if incompatible startup flags are specified
also note that this works only on Matlab installations having JVM 1 5 or higher (i e ,
Matlab release 7 0 4 (R14 SP2) and higher), which supports remote debugging 44 For earlier
releases, add –Xdebug and –Xrunjdwp options to the java.opts file (see Section 1 9) Each
option must be placed on a separate line in the java.opts file:
-Xdebug
and one of the following (the second is for Windows platforms only):45
-Xrunjdwp:transport = dt_socket,address = 4444,server = y,suspend = n
-Xrunjdwp:transport = dt_shmem,address = matlab,server = y,suspend = n
these options are incompatible with some Matlab versions/platforms (particularly modern
Matlab releases), causing Matlab to fail to start without any generated error message
explaining what happened In some cases, Matlab may fail to start after setting the java.
opts options due to a missing jdwp.dll library file required by the Java debugger, as explained
in MathWorks solution 1-OVU1l 46 also, java.opts options apply to all the Matlab sessions,
whereas the –jdb startup flag can be specified only for the rare sessions in which
Matlab–Java debugging is required this is important since the remote Java debugging
entails some overhead on the Matlab/Java side, which, in most cases, when debugging is
unneeded, is undesirable
Here is the complete Matlab–Java debugging process, adapted from a post by Ed Yu on
CSSM 47 this applies to Eclipse IDE, but can easily be adapted for other IDEs:
1 Create an Eclipse project (we must use JDK 1 5 or above); to include the source code
of the Java classes, remember the folder where you put the output classes when you
defined the project
2 Start Matlab with the –jdb command-line startup option (or on pre-R14 Matlab
releases, use the java.opts modification that was explained above)
3 In Matlab, add the folder of the output classes from step 1 into Matlab’s javaclasspath
We can use either static or dynamic classpath here
4 In Eclipse, add a “Remote Java application” debug configuration: Set Connection
type “Standard (Socket attach)”, Host “localhost”, Port 4444
Attaching the Eclipse debugger to a running local MAtlAb process
5 Now click the “Debug” button to debug the “Remote Java application” in Eclipse If
Eclipse fails to connect to Matlab, you will see an error message; otherwise, you
will see no message and will be able to proceed onward
6 Place a breakpoint in the Java code within Eclipse
7 back in Matlab, instantiate or execute the Java code You should see the breakpoint
popping up in Eclipse when Matlab calls the Java code and reaches the first
breakpoint
the steps for using Netbeans IDE are very similar: Instead of steps #4 and 5, simply select
Debug/attach Debugger from the main menu or toolbar, and then select Socketattach to port
4444 or Processattach to the Matlab process ID (which is actually the JVM’s process ID)
Socket attachment is useful for remote (intercomputer) debugging, while process attachment
is useful for local (same computer) debugging Netbeans will automatically attempt the
debug connection upon pressing the OK button, and will then display Matlab’s threads in
a new threads panel, or report an error if the connection failed for any reason:
Attaching Netbeans debugger to a specific socket (useful for remote debugging)
Attaching Netbeans debugger to a specific process (useful for local debugging)
With Netbeans (and possibly also Eclipse), there is a reported problem that Matlab locks
the generated JaR files, preventing recompilation in the IDE a CSSM-suggested workaround
is to point Matlab’s javaclasspath to the Java project’s build/classes folder, rather than to the
JaR file 48 When Java files are modified and saved in the IDE, they are automatically recompiled
and reloaded by Matlab
Profiling memory and CPU usage of Java classes can be done in several ways: we can of
course use the facilities available in our chosen Java IDE both Eclipse49 and Netbeans50 have
extensive support for this, with many important plugins for both IDEs to provide a clear picture
at a very basic level (outside the IDE), we can turn on instruction (-Xt) and method (-Xtm) tracing
via java.opts 51 We can even generate an hprof text file of called methods and timing, similar
to Matlab’s profiler 52
Ed Yu has posted a detailed post about debugging a Java class called from within Matlab 53
He has also posted detailed accounts of his experience, first using a Jbuilder/Eclipse-integrated
OptimizeIt profiler,54 then using an external JProfiler application,55 and finally using an external
YourKit Java profiler 56
Matlab’s built-in profiler can also be used It does not profile the internal steps within the
Java methods and reports the Java profile data at the class (not method) level this is much less
useful than the other profilers, but may still be sufficient for simple Matlab–Java integration
tasks and there is no beating the ease-of-use of using Matlab’s integrated profiler, detailing
both Matlab and Java calls at the same place:
MAtlAb’s integrated Profiler displaying information about Java methods (see bottom row)
Memory profiling is normally part of the profiling tools, but also has some dedicated tools
First, note there are several JVM switches that can be turned on in java.opts: -Xrunhprof[:help]|
[:option = value, ], -Xprof, -Xrunprof, -XX: +PrintClassHistogram and so on 57 there are
several memory-monitoring (“heap-walking”) tools: the standard JDK jconsole, jmap, jhat, and
jvisualvm (with its useful plugins) provide good basic coverage MathWorks has posted a tutorial
on using jconsole with Matlab 58 there are a number of other third-party tools such as
JMP (for JVMs 1 5 and earlier)59 or tIJMP (for JVM 1 6) 60 Within Matlab, we can use
utilities such as Classmexer61 to estimate a particular object's size or use java.lang.
Runtime getRuntime()’s methods62 (maxMemory(), freeMemory() and totalMemory()) to
monitor overall Java memory
Starting in Matlab 7 13 (R2011b), we can use the built-in Java memory monitor:
com.mathworks.xwidgets.JavaMemoryMonitor.invoke
to complete the picture, note that there are several dedicated tools for Java code analysis that
can be used for static or dynamic code coverage and analysis reports 63
1.7 Compatibility Issues
While supporting a large subset of the core Java functionality, some advanced Java constructs
are not accessible via Matlab † Use of Generics,64 introduced in J2SE 5 (Matlab 7 0 4,
R14 SP2), is an example of one such unsupported Java functionality:
>> jCollection = javaObject('java.util.Collection<java.lang.String>');
??? Error using ==>javaObject
No class java.util.Collection<java.lang.String> can be located on Java
classpath
also, Matlab cannot invoke Java code that is not class-wrapped always remember that
the JVM shipped with Matlab is only used to enable Matlab to access Java classes, not
to act as an internal Java interpreter For similar reasons, Java interfaces, annotations, and
anonymous classes and methods (typically used by event callback actions) cannot be directly
accessed from Matlab However, this is not a big limitation, since the Matlab programming
language is very powerful Java code can often be ported into Matlab, or used as-is via
class or object reference another limitation is that inner classes and enumerations cannot be accessed directly: Inner classes can only be accessed via javaObject/javaMethod using ‘ParentClass$InnerClass’ $-notation, but not via the expected standard ParentClass InnerClass dot-notation accessing enumerations is even more awkward, and using $-notation is not sufficient
For example, JVM 1 6 (in Matlab 7 5 R2007b onward) enabled access to the new trayIcon
functionalities (see Section 3 6) One of its functionalities is displaying a message next to the
tray icon, using java.awt.TrayIcon.displayMessage() this method expects an object of
type java.awt.TrayIcon.MessageType,65 which is an enumeration within the TrayIcon
class However, Matlab’s dot-notation does not recognize what should have been the following
correct notation, so we need to resort to Java reflection:
>> trayIcon.displayMessage('title', 'info msg', . . .
TrayIcon.MessageType.INFO);
??? No appropriate method or public field MessageType for class java.awt.
TrayIcon
>> trayIconClasses = trayIcon.getClass.getClasses;
>> trayIconClasses(1)
ans =
class java.awt.TrayIcon$MessageType < =hurray!!!
† these constructs may be interesting only to readers with advanced Java knowledge; other readers may safely skip this
section
>> MessageTypes = trayIconClasses(1).getEnumConstants
MessageTypes =
java.awt.TrayIcon$MessageType[]:
[java.awt.TrayIcon$MessageType] <= 1: ERROR
[java.awt.TrayIcon$MessageType] <= 2: WaRNING
[java.awt.TrayIcon$MessageType] <= 3: INFO
[java.awt.TrayIcon$MessageType] <= 4: NONE
>> trayIcon.displayMessage('title','info msg',MessageTypes(3));
We can also access Java enums using their built-in values() and valueOf() methods:
>>
msgType = javaMethod('valueOf','java.awt.TrayIcon$MessageType','I
NFO')
msgType =
INFO <= a java.awt.TrayIcon$MessageType object
>> enums =
cell(javaMethod('values','java.awt.TrayIcon$MessageType'));
>> msgType = enums{3}; % alternative way to find the INFO
enum value
>> cellfun(@(c)c.toString.char, enums, 'uniform',false)'
ans =
'ERROR' 'WaRNING' 'INFO' 'NONE'
Inner classes can also be accessed using the Java classloader, although this is more
cumbersome 66
trying to access internal static fields in java.nio.channels.FileChannel.
MapMode,67 in order to use them to create a memory-mapped file using FileChannel
map(. . .), is similarly problematic 68 luckily, in this case, we have the built-in memmapfile
Matlab function as a much simpler alternative, but for the record, we could do this:
>> channel = java.io.FileInputStream('234.jpg').getChannel
channel =
sun.nio.ch.FileChannelImpl@1c7a5d3 <= which extends FileChannel
>> innerClasses = ch.getClass.getSuperclass.getDeclaredClasses;
>> innerClasses(1)
ans =
class java.nio.channels.FileChannel$MapMode
>> read_only_const = innerClasses(1).getField('REaD_ONLY').get(1)
read_only_const =
REaD_ONLY <= a java.nio.channels.FileChannel$MapMode object