When debugging Java events in Matlab callbacks, it is sometimes useful to check the stack trace of the originating Java code. Matlab’s built-in dbstack function only reports the stack-trace of Matlab code, and any prior Java code in the stack trace is not reported. Knowing this information is also extremely important when debugging Java components that are used in Matlab, especially when using the Java-to-Matlab Interface (JMI).
Let’s use a specific example to illustrate: Matlab’s uitable passes information back and forth between its underlying Java code and Matlab, via the arrayviewfunc Matlab function (%matlabroot%/toolbox/matlab/codetools/arrayviewfunc.m). If we place a breakpoint in arrayviewfunc and then update the table’s data, dbstack will only report the Matlab stack:
% Prepare an empty uitable >> hTable = uitable('ColumnName',{'a','b','c'}); % Place a breakpoint in arrayviewfunc >> dbstop in arrayviewfunc at reportValuesCallback >> dbstatus Breakpoint for arrayviewfunc>reportValuesCallback is on line 588. % Update the table data and wait for the breakpoint to trigger >> set(hTable,'Data',magic(3)); % Check the Matlab stack trace – no sign of the invoking Java code K>> dbstack > In arrayviewfunc>reportValuesCallback at 588 In arrayviewfunc at 42 |
To see the originating Java stack trace, we can use java.lang.Thread
‘s static dumpStack() method, which spills the Java stack trace onto the stderr console (will appear in red in Matlab’s Command Window):
K>> java.lang.Thread.dumpStack java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Unknown Source) at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method) at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:219) at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121) at com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1550) at com.mathworks.hg.peer.ui.table.DefaultUIStyleTableModel$UITableValueTableModel$1.runOnMatlabThread(DefaultUIStyleTableModel.java:467) at com.mathworks.jmi.MatlabWorker$2.run(MatlabWorker.java:79) at com.mathworks.jmi.NativeMatlab.dispatchMTRequests(NativeMatlab.java:364) |
To access and possibly parse the originating Java stack trace, we can use the following trick:
K>> st = java.lang.Thread.currentThread.getStackTrace; K>> for idx = 2 : length(st), disp(st(idx)); end com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method) com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:219) com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121) com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1550) com.mathworks.hg.peer.ui.table.DefaultUIStyleTableModel$UITableValueTableModel$1.runOnMatlabThread(DefaultUIStyleTableModel.java:467) com.mathworks.jmi.MatlabWorker$2.run(MatlabWorker.java:79) com.mathworks.jmi.NativeMatlab.dispatchMTRequests(NativeMatlab.java:364) |
Each of the stack trace elements can be inspected, to get specific properties:
K>> st(1).getFileName ans = [] % empty = unknown K>> st(2).get Class = [ (1 by 1) java.lang.Class array] ClassName = com.mathworks.jmi.NativeMatlab FileName = NativeMatlab.java LineNumber = [-2] MethodName = SendMatlabMessage NativeMethod = on K>> st(2).isNativeMethod ans = 1 % 1 = true K>> char(st(2).getFileName) % cast java.lang.String to a Matlab char ans = NativeMatlab.java K>> st(2).getLineNumber ans = -2 % negative = unknown K>> st(5).get Class = [ (1 by 1) java.lang.Class array] ClassName = com.mathworks.jmi.Matlab FileName = Matlab.java LineNumber = [1550] MethodName = mtFeval NativeMethod = off |
This works well in JVM 1.5 (i.e., Matlab 7.04 or R14 SP2) and higher. In older Matlab releases you can use a slight modification:
K>> t = java.lang.Throwable; st=t.getStackTrace; K>> for idx = 1 : length(st), disp(st(idx)); end com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method) ... (etc.) |
Hello Yair,
Do you know if there a way to avoid displaying the java stack trace that may appear (some kind of “warning off all” but for java exceptions)?
I have a tree in one of my GUI and it sometimes returns exceptions. This does not prevent the correct execution but my users don’t like red messages they don’t understand and I would like to hide those traces.
Thx
Laurent
@Laurent – I too would love to disable these warnings (actually, these are Java exceptions, but in many cases as you said they act as mere warnings that do not affect code execution). Unfortunately I do not know of any way to suppress them.
so bad…
Thank you for your quick reply and for everything you share with us.
Laurent
[…] unless “dbstop if error” is on. Here is the full stack trace at the point of error (see this post regarding how to generate the Java stack dump): K>> dbstack > In […]