外部进程是否可以强制JVM抛出一个;java.lang.OutOfMemoryError:超出GC开销限制;
在同一操作系统和硬件上运行的另一个进程(java Order not)是否可能触发外部进程是否可以强制JVM抛出一个;java.lang.OutOfMemoryError:超出GC开销限制;,java,jvm,out-of-memory,Java,Jvm,Out Of Memory,在同一操作系统和硬件上运行的另一个进程(java Order not)是否可能触发 java.lang.OutOfMemoryError: GC overhead limit exceeded 通过消耗RAM和/或大量CPU负载,或者通过其他方式 从 详细消息“超出了GC开销限制”表明垃圾收集器一直在运行,Java程序进展非常缓慢。在垃圾收集之后,如果Java进程花费大约98%的时间进行垃圾收集,并且恢复的堆少于2% 我知道这是时间敏感的。然而,对于这98%的人所指的内容,它似乎缺乏适当的规
java.lang.OutOfMemoryError: GC overhead limit exceeded
通过消耗RAM和/或大量CPU负载,或者通过其他方式
从 详细消息“超出了GC开销限制”表明垃圾收集器一直在运行,Java程序进展非常缓慢。在垃圾收集之后,如果Java进程花费大约98%的时间进行垃圾收集,并且恢复的堆少于2% 我知道这是时间敏感的。然而,对于这98%的人所指的内容,它似乎缺乏适当的规范
编辑20201008:添加了是的,但这在现实生活中不太可能 要使JVM抛出
java.lang.OutOfMemoryError:GC开销超出了限制
,必须满足两个条件:
gcheapfleelimit
(2%)李>
import java.util.ArrayList;
public class GCOverheadLimit {
static ArrayList<Object> garbage = new ArrayList<>();
static byte[] reserve = new byte[100_000];
static void fillHeap() {
try {
while (true) {
garbage.add(new byte[10_000]);
}
} catch (OutOfMemoryError e) {
reserve = null;
}
}
public static void main(String[] args) throws Exception {
System.out.println("Filling heap");
fillHeap();
System.out.println("Starting GC loop");
while (true) {
garbage.add(new byte[10_000]);
garbage.remove(garbage.size() - 1);
Thread.sleep(20);
}
}
}
我在一个有CPU配额的cgroup中运行这个程序。我的机器有4个内核,但我让JVM每100毫秒只使用200毫秒的CPU时间
mkdir /sys/fs/cgroup/cpu/test
echo 200000 > /sys/fs/cgroup/cpu/test/cpu.cfs_quota_us
echo $JAVA_PID > /sys/fs/cgroup/cpu/test/cgroup.procs
到目前为止,该计划运作良好。现在,我在同一个cgroup中运行一个或两个CPU燃烧进程:
sha1sum /dev/zero &
echo $! > /sys/fs/cgroup/cpu/test/cgroup.procs
由于超出了配额,操作系统开始限制进程。GC次数增加,JVM最终抛出java.lang.OutOfMemoryError:超出了GC开销限制
注意:重现问题需要仔细选择参数(堆大小、延迟、配额)。其他机器和其他环境的参数将不同。我的观点是-这个问题在理论上是可能的,但在实践中可能永远不会发生,因为有太多的因素需要匹配在一起。当然可以,检查一下如何简单地重现这个问题error@MichalDrozd这个问题是关于触发错误的另一个过程哦,伙计!我尝试了同样的事情(非常接近这个),但没有成功,这非常非常好。但这是否意味着另一个过程会触发错误?这看起来确实像是另一个进程影响了JVM。我不确定这只是我的问题,还是这里的问题是可以相互改变的。@Eugene对我来说,“强制JVM抛出错误”和“触发错误”是可以互换的。事实上,这是一个很好的例子。因此,基本上这归结为机器上的一些沉重的CPU(过度)负载,同时GC承受压力。在一台更大的机器上,即30+HT内核和300+GB的RAM,并行GC本身可能会施加相当多的CPU负载。竞争进程需要多少额外的CPU负载才能“扭转局面”?这仅仅是因为并行GC(大概)将其时间计算基于已用的实时/墙壁时间而不是CPU时间吗?@Andreas Right,GC开销策略计算暂停时间,而不是CPU时间。我不能说大约有30多个内核,但我的观点是——尽管理论上可能是另一个进程导致JVM抛出“GC开销限制”错误,但实际上这并不重要:当可用内存非常低时,无论如何都会有问题。
sha1sum /dev/zero &
echo $! > /sys/fs/cgroup/cpu/test/cgroup.procs