Sometimes I start a MATLAB script and realize too late that it is going to output way too many figures. Eventually I get an
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
which can easily be reproduced on my machine using
for i=1:inf
figure;
end
I get to around ~90 figures before it crashes with the standard setting (Preferences / Java Heap Memory) of 128 MB Java heap, while doubling the Heap to 256 MB gives me around 200 figures.
Do you see any way to avoid the Java error message? If there is not enough memory for another figure, I'd like my script to be told rather than crash.
Maybe I could have a wrapper for figure
which (somehow?) checks how much Java heap is available and which refuses to open a new figure if there is not enough space left?
Update
Using the answers below, I get a nice graph for how much free Memory Java has:
This was produced using
for i=1:inf
java.lang.Runtime.getRuntime.gc
fprintf('%3.0f: %1.0f Byte free\n',i,java.lang.Runtime.getRuntime.freeMemory);
figure;
end
I assume the increase in the beginning means that garbage collection only does a certain effort every time I call it?
Update 2 - my solution
Using the help I got here, I implemented the following solution as a figure.m
which overloads and calls the build-in figure
command:
function varargout=figure(varargin)
memcutoff = 10E6; % keep at least this amount of bytes free
memkeyboard= 3E6; % if memory drops below this, interrupt execution and go to keyboard mode
global refuse_new_figures
if refuse_new_figures
warning('jb:fig:lowjavamem2','Java WAS memory low -> refusing to create a new figure. To reset, type "global refuse_new_figures ; refuse_new_figures = [];"');
return
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
if freemem < memcutoff
fprintf('Free memory is low (%1.0f Bytes) -> running garbace collector...\n',freemem);
java.lang.Runtime.getRuntime.gc
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
% fprintf('Free memory is %1.0f Bytes.\n',freemem);
if freemem < memkeyboard
warning('jb:fig:lowjavamem','Java memory very low -> going into interactive mode. Good luck!');
keyboard;
end
if freemem < memcutoff
warning('jb:fig:lowjavamem','Java memory low -> refusing to create a new figure!');
refuse_new_figures=true;
else
if nargin > 0
if nargout > 0
varargout{1}=builtin('figure',varargin{:});
else
builtin('figure',varargin{:});
end
else
if nargout > 0
varargout{1}=builtin('figure');
else
builtin('figure');
end
end
end
In general, I'd suggest setting maximum Java Heap Memory to about 25% of the available RAM, which allows you to open lots of figures (but not infinite numbers). If you cannot do this in the preferences (e.g. b/c you have a Mac like mine), this solution will help - it overrides the preference settings.
The linked solution also tells you how much free java memory you have left, and how much total is available: Run the following commands:
java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory
Unfortunately, a figure doesn't take a fixed amount of Java memory, an empty figure takes much less than one displaying 10k points, and a minimized figure takes less memory than a maximized one. However, if you can estimate the average memory needed per figure, you can indeed write a wrapper for figure
that checks whether it's likely that this figure will be the last. Alternatively/additionally, you could make the wrapper function minimize all other figures (see Undocumented Matlab for this).
EDIT As pointed out by @Peter Lawrey, you may also try and perform garbage collection before checking how much memory is available - though I don't know whether Matlab would try that, anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With