Java 当打开太多数字时,如何避免MATLAB崩溃?

Java 当打开太多数字时,如何避免MATLAB崩溃?,java,matlab,heap-memory,jvm-crash,Java,Matlab,Heap Memory,Jvm Crash,有时,我启动一个MATLAB脚本,但意识到它将输出太多的数字太晚了。最终我得到了一份工作 线程“AWT-EventQueue-0”java.lang.OutOfMemoryError中出现异常:java堆空间 可以在我的机器上使用 for i=1:inf figure; end 在128 MB Java堆的标准设置()崩溃之前,我得到了大约90个数字,而将堆加倍到256 MB会得到大约200个数字 您是否找到了避免Java错误消息的方法?如果没有足够的内存存储另一个图形,我希望我的脚本能够

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

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

可以在我的机器上使用

for i=1:inf
  figure;
end
在128 MB Java堆的标准设置()崩溃之前,我得到了大约90个数字,而将堆加倍到256 MB会得到大约200个数字

您是否找到了避免Java错误消息的方法?如果没有足够的内存存储另一个图形,我希望我的脚本能够被告知,而不是崩溃

也许我可以为
figure
创建一个包装器,它(不知怎么的?)检查有多少Java堆可用,如果没有足够的空间,它会拒绝打开一个新的figure

更新

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

这是使用

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
函数varargout=图(varargin)
memcutoff=10E6;%至少保留此数量的可用字节
memkeyboard=3E6;%如果内存低于此值,请中断执行并转到键盘模式
全球垃圾新数字
如果拒绝新的数字
警告('jb:fig:lowjavamem2','Java内存不足->拒绝创建新图形。若要重置,请键入“全局拒绝新图形;拒绝新图形=[];”);
返回
结束
freemem=java.lang.Runtime.getRuntime.freeMemory;
如果freemem正在运行garbace收集器…\n',freemem);
java.lang.Runtime.getRuntime.gc
结束
freemem=java.lang.Runtime.getRuntime.freeMemory;
%fprintf('可用内存为%1.0f字节。\n',freemem);
如果freemem进入交互模式。祝你好运!');
键盘
结束
如果freemem拒绝创建新图形!');
拒绝新数字=正确;
其他的
如果nargin>0
如果nargout>0
varargout{1}=builtin('figure',varargin{:});
其他的
内置('figure',varargin{:});
结束
其他的
如果nargout>0
varargout{1}=内置('figure');
其他的
内置(“图”);
结束
结束
结束

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

链接的解决方案还告诉您还有多少可用java内存,以及总共有多少可用内存:运行以下命令:

java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory 
不幸的是,一个图形不需要固定的Java内存,一个空的图形比一个显示10k点的图形占用更少的内存,一个最小化的图形比一个最大化的图形占用更少的内存。但是,如果您可以估计每个图所需的平均内存,那么您确实可以为
编写一个包装器,检查这个图是否可能是最后一个。或者/另外,您可以使包装器函数最小化所有其他图形(为此)


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

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

您可以使用Runtime.gc()和Runtime.freemory()


如果不设置最大内存,它将占可用内存的百分比。

我在自己的函数“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
函数y=limfig
imglimit=15;

如果length(findobj('type','figure')freemory只告诉您现在有多少可用空间,而不是如果您执行了GC,那么会有多少可用空间。GC总是在JVM抛出OutOfMemory错误之前自动发生,因此,显式调用
Runtime.GC()
并不是真正需要释放空间的,但这肯定有助于获得正确的可用内存数据。需要记住的一点是,VM决定何时进行GC,
Runtime.GC()
调用并不会在任何情况下都导致垃圾收集。Matlab将为程序设置最大可用java内存,我们所能做的就是选择该内存的大小。更新很好。如果可以的话,我会第二次投票。我想知道这是否是因为Java分配了更多的内存。