15

有时我启动一个 MATLAB 脚本并意识到它会输出太多的数字为时已晚。最终我得到一个

线程“AWT-EventQueue-0”java.lang.OutOfMemoryError 中的异常:Java 堆空间

可以很容易地在我的机器上使用

for i=1:inf
  figure;
end

在 128 MB Java 堆的标准设置( Preferences / Java Heap Memory )崩溃之前,我达到了大约 90 个数字,而将堆增加到 256 MB 给我大约 200 个数字。

您有什么方法可以避免Java 错误消息吗?如果没有足够的内存容纳另一个人物,我希望我的脚本被告知而不是崩溃。

也许我可以有一个包装器figure(不知何故?)检查有多少Java堆可用,如果没有足够的空间,它拒绝打开一个新图形?

更新

使用下面的答案,我得到一个很好的图表,显示 Java 有多少可用内存:

figure;plot(freeMem/1E6,'x');ylabel('java.lang.Runtime.getRuntime.freeMemory [MB]');xlabel('创建的空图数');

这是使用

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

我假设一开始的增加意味着垃圾收集每次调用时只做一定的努力?

更新 2 - 我的解决方案

使用我在这里获得的帮助,我实现了以下解决方案作为figure.m重载并调用内置figure命令:

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
4

3 回答 3

6

一般来说,我建议将最大 Java 堆内存设置为可用 RAM 的 25% 左右,这样您就可以打开很多数字(但不是无限数字)。如果您无法在首选项中执行此操作(例如,b/c 您有像我这样的 Mac),此解决方案将有所帮助 - 它会覆盖首选项设置。

链接的解决方案还告诉您剩余多少可用 Java 内存,以及可用的总内存量:运行以下命令:

java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory 

不幸的是,一个图不占用固定数量的 Java 内存,一个空图比显示 10k 点的图要少得多,最小化的图比最大化的图占用更少的内存。但是,如果您可以估计每个图所需的平均内存,您确实可以编写一个包装器来figure检查该图是否可能是最后一个。或者/另外,您可以使包装函数最小化所有其他数字(参见未记录的 Matlab)。

编辑正如@Peter Lawrey所指出的,您也可以在检查可用内存量之前尝试执行垃圾收集 - 尽管我不知道 Matlab 是否会尝试这样做。

于 2011-06-01T12:49:03.863 回答
2

您可以检查空闲内存,如果没有足够的触发 GC 并再次检查。如果还不够,就失败。您可能希望允许 1-10 MB 的头部空间。

您可以使用 Runtime.gc() 和 Runtime.freeMemory();

如果您不设置最大内存,它将使其成为可用内存的百分比。

于 2011-06-01T12:49:12.990 回答
1

我在我自己的函数 'limfig' 中使用了 findobj 函数,其中 imglimit 设置您希望一次允许打开的图形数量。

function y=limfig
imglimit=15;
if length(findobj('type','figure'))<imglimit
    y=figure; 

else
    'too many figures already open'
    return
end
end

将此短代码保存为 limfig.m,然后在任何其他代码中使用 f=limfig 行而不是 f=figure。

于 2016-08-16T07:29:35.527 回答