Today I would like to introduce guest blogger Roderick, who wishes to remain anonymous. Roderick discusses his experience with setting up Matlab to use the latest stable release of Java, namely JVM 1.7, a.k.a. Java 7.
Background and executive summary
I work in the team where I do a lot of research and prototyping with Matlab. The final production code is however coded by a separate development team in Java 7. When running back-tests on our models I have to either ensure my Matlab prototype exactly matches the Java behavior, or to call the Java production code directly. However, although Java 7 has been available since July 2011, the latest official Matlab version (R2013a at this point) still uses the JVM 1.6 (Java 6), which does not allow calling Java 7 code directly. Today’s article contains my experience in trying to let Matlab use JVM 1.7 code.
I urge readers to consider the following before trying the hacks I’ve found:
- The hacks described below were found to work for Matlab R2012b and R2013a on Windows 64bit. Simulink or any Matlab toolboxes were not tested, nor any other operating systems (although I’ve found most solutions to work on Linux as well).
- The set of hacks is not complete; some issues remain in the setup of Matlab to use Java 7.
- As with all other undocumented Matlab features, they may break in future Matlab versions.
- A future Matlab version (possibly as close as the upcoming R2013b) might be updated use Java 7 natively – the hacks should only be used on versions that have JVM 1.6.
It is worth considering a number of alternatives before trying to setup Matlab with the JVM 1.7:
- Compiling the Java project using JDK 1.6 instead of JDK 1.7. If you have the source code for a project and no specific Java 7 features are being used in the code, you could simply recompile it using JDK 1.6 or even 1.5. This would be a more advisable approach than switching Matlab to use Java 7, and enable full backward compatibility on Matlab releases as old as R2007b (for 1.6) or R14 SP2 (for 1.5).
- Use Java Remote Method Invocation (Java RMI). This enables using Java 6 Java code that calls the Java 7 code. It requires some more work starting off, but has the benefit of not needing to switch Matlab to use Java 7. Due to using a different Java virtual machine, it also prevents duplicate dependencies between Matlab and Java code, when a Java project depends on Java libraries on which Matlab also depends. If Java code relies on a different version than Matlab for such a library, this may give problems with the Java classloader that could result in Matlab being unable to add Jar-file(s) to the java classpath – this issue is solved by separating the Java 7 code to use an independent JVM. The Java RMI approach appears to be a longer-term solution than hacking Matlab to use JVM 1.7.
If after considering the alternatives you have a valid use-case for Matlab to call Java 7 code, follow these steps:
- Download the latest Matlab release if you can; earlier releases have more issues with JVM 1.7
- Setup Matlab to use JVM 1.7
- Create a startup function to detect if JVM 1.7 is used; if so, update the default figure’s CreateFcn to force visibility and then use drawnow
- Enable the
UseOldFileDialogs
feature - Copy and patch listdlg.m to remove the hardcoded figure CreateFcn callback override
- Copy and patch gui_mainfcn.m to force visibility of GUI objects by using uistack and by recursively flipping the order of all Children property, or by using the supplied code below
The text below details these steps.
Switching Matlab to use the JVM 1.7
To run Java 7 code from Matlab, Matlab needs to use JVM 1.7. To do this, see this MathWorks page, or follow these steps:
- Ensure that you are using Java 6 or earlier – no need to do anything if your Matlab already has Java 7
>> version -java ans = Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) 64-Bit Server VM mixed mode
- Download and install JRE 1.7 or JDK 1.7 from the Oracle website
- Create a new System Environment Variable called
MATLAB_JAVA
with the installation folder as its value. For example: “C:\Program Files\Java\jdk1.7.0_21\jre” - Restart Matlab and verify that it picked up the new Java version:
>> version('-java') ans = Java 1.7.0_21-b11 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
Problems and workarounds with Matlab using JVM 1.7
Certain Matlab functionality was found to give issues when using the JVM 1.7. Most problems are related to visibility and display, although most Matlab code ran as-is without issue.
A) Matlab hangs after “Save As” or “Import Data”
Matlab hangs after clicking the <Import Data> button, or when trying to use the <Save As> functionality. This problem seems to be related to opening a certain type of window after which focus is not returned to Matlab. The user is forced to close Matlab via the Windows Task Manager. This problem was found in R2012b and earlier, however it seems fixed in R2013a. I have not found a solution for this problem; perhaps it is related to this issue. Consider importing data via the command line, and first creating a new m-file then open it in the Matlab Editor. Alternatively, if you really get annoyed by this, you could use findobj functionality to disable the Matlab buttons.
B) Java exceptions from java.awt
Exceptions are occasionally thrown when multiple monitors are used, e.g. when moving figures from one screen to the other, or when docking figures. These exceptions can be a bit annoying, but they do not seem critical.
C) Matlab R2012b hangs using uigetfile
Matlab freezes when using uigetfile. It seems R2013a does not have this problem; for R2012b a solution was found by setting the undocumented UseOldFileDialogs
feature:
feature('UseOldFileDialogs', 1) |
D) Defective Matlab dialog windows
Certain Matlab dialogs, such as questdlg, listdlg and inputdlg are missing some components. For example:
ButtonName = questdlg('What is your favorite color?', 'Color Question', 'Red', 'Green', 'Blue', 'Green'); |
The problem seems to be related to visibility of the objects, whereby the command buttons or input text objects are part of the figure, but they are just not displayed. The same problem was found for Matlab GUIs that are created by Matlab users and in guide.
Solution: force the figure visibility in its CreateFcn callback, by setting the Visible property to ‘on’ and using drawnow.
set(0, 'DefaultFigureCreateFcn', @DefaultFigureCreationFcnForJVM7); function DefaultFigureCreationFcnForJVM7(aObject, aEventdata) % PURPOSE: This function acts as the default figure create function to enforce focus for UI dialog objects % when using JVM 7. % IN: - aObject (1x1 float): the handle to figure object % - aEventdata (1x1 struct): the event data myDbStack = dbstack(); if length(myDbStack) > 1 && any(strcmp(myDbStack(2).file, 'hgloadStructDbl.m')) % don't force visibility when GUIs are opened else set(aObject, 'Visible', 'on'); drawnow(); end |
The UI dialogs flash a bit more when created, due to the fact that they resize and move around the screen for optimal placement. But at least they look ok now:
This solution works for all dialogs except listdlg, which is hardcoded to disable the figure’s CreateFcn. For listdlg, follow these steps:
- Find listdlg.m
>> which listdlg C:\Program Files\MATLAB\R2013a\toolbox\matlab\uitools\listdlg.m
- Copy listdlg.m to a personal folder and comment out the figure’s CreateFcn override in the copied file:
fig_props = { ... 'name' figname ... 'color' get(0,'DefaultUicontrolBackgroundColor') ... 'resize' 'off' ... 'numbertitle' 'off' ... 'menubar' 'none' ... 'windowstyle' 'modal' ... 'visible' 'off' ... ... % comment out the createfcn to empty such that we don't override the specific createfcn for JVM 1.7! ... %'createfcn' '' ... 'position' fp ... 'closerequestfcn' 'delete(gcbf)' };
- Similarly, copy the private functions getnicedialoglocation.m and setdefaultbutton.m and place their entire contents at the end of your copied listdlg.m.
- Ensure that your personal folder is higher on the Matlab path than toolbox\matlab\uitools\
E) Custom GUI visibility problems
If you developed custom Matlab GUIs, you might notice visibility problems when opening the GUIs. For example, assume we have developed the following simple GUI:
If we try to open this GUI we see missing objects again:
This problem seems related to the one with the Matlab dialogs, however it does not seem to be resolved by forcing visibility upon figure creation. After much trial and error, it seems we can fix this by playing around with the order of the figure’s Children:
myFigureHandle = TestGUI; myChildHandles = get(myFigureHandle, 'Children') set(myFigureHandle, 'Children', flipud(myChildHandles)) |
Notice that flipping the order of Children in the main figure did not resolve the visibility of objects in the panels. The procedure needs to be done recursively for all the figure’s containers. One more step gives:
set(myChildHandles(1), 'Children', flipud(get(myChildHandles(1), 'Children'))) |
Solution: for a single solution that applies to all GUIs, you can do the following:
- Locate gui_mainfcn.m
>> which gui_mainfcn C:\Program Files\MATLAB\R2013a\toolbox\matlab\guide\gui_mainfcn.m
- Copy gui_mainfcn.m to a personal folder and add a new call to a specific function for handling JVM7 issues for GUIs. The location of this function is important, put it just after the following feval command:
... feval(gui_State.gui_OpeningFcn, gui_hFigure, [], guidata(gui_hFigure), varargin{:}); % Patched logic to ensure visibility of all objectsHandleJvm7SupportForGUIs(gui_hFigure, guidata(gui_hFigure));...
- Place the following code at the end of your copied gui_mainfcn.m file:
function HandleJvm7SupportForGUIs(aGUIObject, aGUIHandles) % PURPOSE: This function hacks around with the focus of objects on a GUI. It was found that GUIs do not % work as intended with the jvm 7 setup, and that objects on panels lose focus/visibility. % The approach which at is taken now is by flipping the order of childrens in uipanels. % Before the order is swapped, the panel is set to be the visible top-layer panel. % IN: - aGUIObject (1x1 float): the handle the GUI figure % - aGUIHandles (1x1 struct): the GUI handles if ~IsJvm7Used() return end myListOfHandleArrayFields = 'tabPanels'; try set(aGUIObject, 'Visible', 'on'); drawnow(); if isprop(aGUIObject, 'Children') myChildren = get(aGUIObject, 'Children'); myIsMenuItem = false(length(myChildren), 1); for i = 1:length(myChildren) if isprop(myChildren(i), 'Type') && strcmp(get(myChildren(i), 'Type'), 'uimenu') myIsMenuItem(i) = true(); end end myChildren(~myIsMenuItem) = flipud(myChildren(~myIsMenuItem)); set(aGUIObject, 'Children', myChildren); drawnow(); end myFields = fieldnames(aGUIHandles); myIsValid = true(size(myFields)); for i = 1:length(myListOfHandleArrayFields) myIsValid = myIsValid & cellfun('isempty', strfind(myFields, myListOfHandleArrayFields{i})); end myFields = myFields(myIsValid); myPanelFields = {}; for i = 1:length(myFields) if isprop(aGUIHandles.(myFields{i}), 'Type') && strcmp(get(aGUIHandles.(myFields{i}), 'Type'), 'uipanel') myPanelFields = [myPanelFields; myFields(i)]; %#ok end end for i = 1:length(myPanelFields) % allow three layers of panels maximum! if isprop(aGUIHandles.(myPanelFields{i}), 'Parent') myParent = get(aGUIHandles.(myPanelFields{i}), 'Parent'); if strcmp(get(myParent, 'Type'), 'uipanel') if isprop(myParent, 'Parent') mySecondParent = get(myParent, 'Parent'); if strcmp(get(mySecondParent, 'Type'), 'uipanel') uistack(mySecondParent, 'top'); drawnow(); end end uistack(myParent, 'top'); drawnow(); end end uistack(aGUIHandles.(myPanelFields{i}), 'top'); drawnow(); set(aGUIHandles.(myPanelFields{i}), 'Children', flipud(get(aGUIHandles.(myPanelFields{i}), 'Children'))); drawnow(); end catch myException disp(['WARN: could not initialize the GUI correctly with JVM 1.7 override logic, in ', mfilename()]); myException.getReport() end function theIsJvm7Used = IsJvm7Used() % PURPOSE: To indicate if Matlab is setup to use jvm 7 % OUT: - theIsJvm7Used (1x1 logical): whether or not JVM 7 is used myJavaVersion = version('-java'); theIsJvm7Used = strcmpi(myJavaVersion(1:8), 'java 1.7');
- Ensure that your personal folder is higher on the Matlab path than toolbox\matlab\uitools\
Notice that the panel names are still missing. So far no solution for this has been found. Perhaps this can be overcome using the fact that uipanel titles are simply hidden children of the panel object.
Depending םn the Java features needed, another possibility is to stick to JVM 5/6 but use another JVM language to write the relevant code e.g. Groovy or Scala – see here for Groovy. Those implement some features made available in Java 7 e.g. strings in switch statements, but using JVM 5/6 compatible bytecode.
Looks like MATLAB R2013b (prerelease) have finally updated to Java 7
i had completed my project in java using eclipse platform
can u help me to execute the same in matlab
very urgent
Hello Yair,
I am working now with matlab R2013B and it appears that cursor does not update correctly on javacomponents… When I set cursors with jComponent.setCursor(aCursor), the cursor does not change when the mouse pointer hovers the component. It always appear as com.mathworks.hg.peer.FigureClientProxy$FigureDTClientBase’s cursor (controlled by the figures’s ‘pointer’ property), which is the first component for which cursor is set in the upwards JavaFrame hierarchy.
I suspect it has something to deal with the new lightweight implementation of hgjavacomponent’s container (great news!). But I am sure that you perfectly know this issue, that’s why I wondered if you had fixed this?
@Julien – I confirm your observation but I’m sorry to disappoint you that I haven’t looked into this so far. I suspect that this is a Java thing, so I advice that you search the Java forums. Please get back here and report if you discover anything useful.
Thanks for your fast answer, Yair. I already had a look on java forums and I did not find anything similar… For example, if you simply create a
JFrame
, add a component to the content pane and set its cursor from matlab command line, it works fine.I look forward to see your investigations!
I tried Matlab R2014a with Java JDK8. Normal plots and the GUI’s from standard matlab work correct.
[…] if you do not have access to the source code, or if it uses some new JDK features), then consider installing a newer compatible JVM in Matlab.Note that when we try running the Java classes using the java executable (outside Matlab), we do […]
Hi yair,
Thanks for your hard work, it’s really help me a lot.
I have a problem with matlab r2013a ja builder, jar created by deploytool is working as expected in jdk 1.8 but figure is shown and dissapear again (figure contain no plot).
Then i change jdk to 1.6u17 (64 bit) to match matlab version but when i run the jar again but it give following error in netbeans :
Any suggestion, how to fix it? i really need the plot for presentation.
@Wayan – it appears that some of your external Java classes (
SimultanBoxGraph
and possibly others) were compiled with JDK 1.7 (=51.0), and this does not work with 1.6. If you can, try recompiling everything using 1.6.Alternatively, try retrofitting your Matlab with JDK 1.7, as explained here.
Alternatively, upgrade to Matlab R2013b (8.2) or newer, which uses 1.7 out-of-the-box.
Alternatively, try figuring out the problem with the disappearing figure in 1.8, using MathWorks support (then return here to let us know if you discover anything useful).
Thank you yair this actually solve my problem.
My bad, i was unaware deploytool use my default 1.7 jdk instead of jdk 1.6 that come from with MATLAB so i didnt recompile it that time.
This step works for me, set new JAVA_HOME variable to jdk 1.6 and recompile everything with deploytool.
Sorry yair, i have one more question about matlab ja builder, my m script run about 2-4 second in matlab but in java it run up to 2 minutes, is it normal? may i ask your suggestion to make it run faster in java?
I have a presentation about it, i dont want they think my program is slow because of inefficient algorithm.
Oh the script is simple, just about function optimization and draw plot of function.
See http://undocumentedmatlab.com/blog/speeding-up-compiled-apps-startup
I came here since I wanted to run an old version MATLAB on Win8. I wasn’t intending to test with the newer jre. But it could not find the default jre, and it turns out this is a msvcr71.dll problem. I just googled a copy of that dll and placed it in C:\Program Files (x86)\MATLAB\R2010a\bin\win32, and the problem is solved.
Source: https://www.mathworks.com/matlabcentral/newsreader/view_thread/271589
I tried out Matlab 2011b and JVM 1.8
The GUI ist starting and plots are shown well.
If I set the figure visible off, an then set the figure visible on, there are just the axes elements, but no buttons or anything else.
Anybody with an idea to fix that?
Thanks!!
@Flo – R2011b uses JVM 1.6 by default – you’re trying to run it with a version that is 2 full generations newer, so I’m not surprised that some things simply don’t work. Try using 1.7, maybe you’ll have better luck…