java - 打开太多图形时如何避免 MATLAB 崩溃?

标签 java matlab heap-memory jvm-crash

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

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

可以很容易地在我的机器上复制

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('number of empty figures created');

这是用

制作的
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

最佳答案

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

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

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

不幸的是,图形并不占用固定数量的 Java 内存,空图形占用的内存远少于显示 10k 点的图形,最小化图形占用的内存少于最大化图形。但是,如果您可以估计每个图形所需的平均内存,您确实可以为 figure 编写一个包装器来检查该图形是否可能是最后一个。或者/另外,您可以使包装函数最小化所有其他数字(为此 see Undocumented Matlab)。

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

关于java - 打开太多图形时如何避免 MATLAB 崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6201272/

相关文章:

java - 是否可以在android中建立多个蓝牙通信

matlab - 如何在 MATLAB 中中止程序执行?

matlab - Octave 是否支持像 Matlab 一样的枚举?

Android Activity 由于堆 fragment 导致服务崩溃

java - 是什么决定了两个竞争线程中的哪一个获得锁?

java - 如何在 Eclipse RCP 3 中使用 dnd 打开新编辑器

java - J2SE 上的 DataSource 和 DriverManager

matlab - 在Matlab中判断一幅图像是否为灰度

java - 计算 JVM 的已用内存

java - 如何使用j2me在运行时识别移动堆内存?