同步操作将从 flatfish/Java-Review 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
内存溢出相对于内存泄漏来讲,尽管更容易被理解,但是同样的,内存溢出也是引发程序崩溃的罪魁祸首之一
由于GC一直在发展,所以一般情况下,除非应用程序占用的内存增长速度非常快,造成垃圾回收已经跟不上内存消耗的速度,否则不是很容易出现OOM的情况
大多情况下,GC会进行各种年龄段的垃圾回收,实在不行了就放发招,来一次Full GC,这个时候会释放大量的内存
javadoc中对OutOfMemoryError的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存
首先说没有空闲内存的情况:说明Java虚拟机的堆内存不够,
这里隐含着一层意思,在抛出OutOfMemoryError之前,通常垃圾收集器会被触发尽其所能去收集空间
当然,也不是任何情况下垃圾回收器都会被触发的
举例
Stop The World 简称STW,指的是GC事件发生的过程中,会产生应用程序的停顿,停顿产生的时候整个应用程序线程都会被暂停,没有任何响应 有点卡死的感觉
被STW中断地应用会在完成GC之后恢复,频繁中段会让用户感觉像是网速不快造成电影卡带一样。
STW事件和采用哪款GC无关,所有地GC都有整个事件
哪怕是G1也不能完全避免STW,只能说垃圾回收器越来越优秀,回收效率越来越高。尽可能地缩短了暂停地时间
STW是JVM后台自动发起和完成的 在用户不可见的情况下,把用户正常的工作线程全部停掉
开发中不要使用System.gc() 会导致Stop-the-world的发生
二者对比
垃圾回收的并发与并行
并行(Parallel):指多条垃圾回收线程并行工作,但此时用户线程仍处于等待状态
串行(Serial)
程序执行时并非在所有地方都能停下来开始GC,只有在特定位置才能停下来开始GC。这些位置称为 “安全点(Safe Point)”
Safe Point的选择十分重要。如果太少可能导致GC等待的时间太长,太频繁就会导致运行时的性能问题
通常会根据**“是否具有让程序长时间执行的特性”**为标准。比如:选择一些执行指令作为 Safe Point ,如方法调用、循环跳转、异常跳转等
如何在GC发生时,检查所有的线程都跑到最近的安全点停顿下来呢?
安全区域
具体的解释见 : Java基础学习/Java - 多线程 - 增强篇 - 四种引用类型.md
Java中有四种引用类型,分别是如下四种
// 只要 o 还指向Object对象,对象 o 就不会被GC回收
Object o = new Object();
o = null;
-Xms2M -Xmx3M
JVM初始内存设为2M,最大可用内存为3M/**
* VM参数:-Xms2M -Xmx3M
*/
public class Test2 {
public static void main(String[] args) {
byte[] bytes = new byte[1024 * 1024 * 3];
}
}
// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
/**
* VM参数:-Xms2M -Xmx3M
*/
public class TestSoftReferenceOom {
private static List<Object> list = new ArrayList();
public static void main(String[] args) {
testReferenceOom();
}
public static void testReferenceOom() {
for (int i = 0; i < 10; i++) {
byte[] b = new byte[1024 * 1024];
SoftReference<byte[]> reference = new SoftReference<>(b);
list.add(reference);
}
// 触发一次GC 注意:并不是一定会立刻执行GC
System.gc();
for (int i = 0; i < list.size(); i++) {
Object obj = ((SoftReference) list.get(i)).get();
System.out.print(obj + " ");
}
}
}
// null null null null null null null null null [B@1540e19d
/**
* VM参数:-Xms2M -Xmx3M
*/
public class TestSoftReferenceOom {
private static List<Object> list = new ArrayList();
public static void main(String[] args) {
testReferenceOom();
}
public static void testReferenceOom() {
byte[] b = null;
for (int i = 0; i < 10; i++) {
b = new byte[1024 * 1024];
SoftReference<byte[]> reference = new SoftReference<>(b);
list.add(reference);
}
// 触发一次GC 注意:并不是一定会立刻执行GC
System.gc();
for (int i = 0; i < list.size(); i++) {
Object obj = ((SoftReference) list.get(i)).get();
System.out.print(obj + " ");
}
}
}
// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
/**
* VM参数:-Xms2M -Xmx3M
*/
public class TestSoftReferenceOom {
private static List<Object> list = new ArrayList();
public static void main(String[] args) {
testWeakReferenceOom();
}
public static void testWeakReferenceOom() {
for (int i = 0; i < 10; i++) {
byte[] b = new byte[1024 * 1024];
WeakReference<byte[]> reference = new WeakReference<>(b);
list.add(reference);
}
System.gc();
for (int i = 0; i < list.size(); i++) {
Object obj = ((WeakReference) list.get(i)).get();
System.out.print(obj + " ");
}
}
}
// null null null null null null null null null null
public class PhantomReference<T> extends Reference<T> {
public T get() {
return null;
}
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}
public void test() {
Map map;
// 弱引用 HashMap
map = new WeakHashMap();
for (int i = 0; i < 10000; i++) {
map.put("key" + i, new byte[i]);
}
// 强引用HashMap
map = new HashMap();
for (int i = 0; i < 10000; i++) {
map.put("key" + i, new byte[i]);
}
}
类型 | 回收时间 | 使用场景 |
---|---|---|
强引用 | 一直存活,除非GC Roots不可达 | 所有程序的场景,基本对象,自定义对象等。 |
软引用 | 内存不足时会被回收 | 一般用在对内存非常敏感的资源上,用作缓存的场景比较多,例如:网页缓存、图片缓存 |
弱引用 | 只能存活到下一次GC前 | 生命周期很短的对象,例如ThreadLocal中的Key。 |
虚引用 | 随时会被回收, 创建了可能很快就会被回收 | 业界暂无使用场景, 可能被JVM团队内部用来跟踪JVM的垃圾回收活动 |
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。