垃圾回收
1. 如何判断对象可以回收
2. .垃圾回收算法
3. 分代垃圾回收
4. 垃圾回收器
5. 垃圾回收调优

1. 如何判断对象可以回收

1.1 引用计数法
给对象添加一个引用计数器,每当有一个地方引用它时,计数器加1。引用失效时,计数器减1 。当计数器为0时,对象就不可能再被使用。---------残留问题:循环引用

1.2 可达性分析算法
通过Gc-Root的对象为起点,通过这个节点向下搜索,搜索所走过的路径为引用链。当一个对象到Gc-Root没有任何引用链连接时,证明对象不可用。

  • 可作为Gc-Root的对象:

    • 虚拟机栈中的引用对象。
    • 本地方法栈中引用的对象。
    • 方法区类静态属性引用的对象。
    • 方法区中常量引用的对象。

可视化看哪些可以作为GC-Root对象

1.3 四种引用

  1. 强引用

    • 只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收,GC Roots直接或间接引用的对象为强引用。
  2. 软引用(SoftReference)

    • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象
    • 可以配合引用队列来释放软引用自身,当软引用引用的对象被垃圾回收后,该软引用就会进入引用队列(下图所示)
  3. 弱引用(WeakReference)

    • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
    • 可以配合引用队列来释放弱引用自身,当弱引用引用的对象被垃圾回收后,该弱引用就会进入引用队列(下图所示)
  4. 虚引用(PhantomReference)

    • 必须配合引用队列使用,主要配合 ByteBuffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存
  5. 终结器引用(FinalReference)

    • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才能回收被引用对象


为什么需要引用队列:因为软,弱引用本身也占有内存,当放到引用队列后,可以变量查看它们是否被强引用引用着,再做后续处理。

虚引用


创建ByteBuffer对象时会创建一个Cleaner虚引用对象,ByteBuffer会被分配一个直接内存,并且把直接内存地址传递给虚引用对象,这样做的目的:将要ByteBuffer一旦没有了强引用,ByteBuffer自己可以被垃圾回收掉,但是还不够,因为它分配的直接内存并不能被java所管理,所以就要在ByteBuffer被回收时让虚引用对象入引用队列, 后台有 Reference Handler 线程会到引用队列找虚引用对象,调用虚引用相关方法释放直接内存;

关于ByteBuffer直接内存的分析在JVM----①内存结构直接内存有讲到。

演示软引用

//jvm 启动参数设置 -Xmx20m 堆为20M
public class Demo2_3 {private static final int _4MB = 4 * 1024 * 1024;//4Mpublic static void main(String[] args) throws IOException {List<byte[]> list = new ArrayList<>();for (int i = 0; i < 5; i++) {list.add(new byte[_4MB]);}}测试上面会发生:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space如果 List<byte[]> list = new ArrayList<>(); list里面的byte数组是读取很大很大很大很大的网络资源,就没有必要一定要保证准确性,可以在不影响主业务的情况下能够完成就可以了,这里就可以用软引用进行改进------------------use SoftReference improve--------------------------
//同样 jvm 启动参数设置 -Xmx20m 堆为20M
public static void soft() {// list --> SoftReference --> byte[]List<SoftReference<byte[]>> list = new ArrayList<>();for (int i = 0; i < 5; i++) {SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);System.out.println(ref.get());list.add(ref);System.out.println(list.size());}System.out.println("循环结束:" + list.size());for (SoftReference<byte[]> ref : list) {System.out.println(ref.get());}}
}输出:
[B@7f31245a
1
[B@6d6f6e28
2
[B@135fbaa4
3
[B@45ee12a7
4
[B@330bedb4
5
循环结束:5
null
null
null
null
[B@330bedb4  //最后list只有一个byte[]了,对应上面加的第5个元素添加参数-Xmx20m -XX:+PrintGCDetails -verbose:gc测试:
[B@7f31245a
1
[B@6d6f6e28
2
[B@135fbaa4
3
[GC (Allocation Failure) [PSYoungGen: 1941K->504K(6144K)] 14229K->13007K(19968K), 0.0012398 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
[B@45ee12a7
4
[GC (Allocation Failure) --[PSYoungGen: 4712K->4712K(6144K)] 17215K->17215K(19968K), 0.0036470 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 4712K->4586K(6144K)] [ParOldGen: 12503K->12465K(13824K)] 17215K->17052K(19968K), [Metaspace: 3246K->3246K(1056768K)], 0.0168497 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]
[GC (Allocation Failure) --[PSYoungGen: 4586K->4586K(6144K)] 17052K->17060K(19968K), 0.0011425 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 4586K->0K(6144K)] [ParOldGen: 12473K->649K(8704K)] 17060K->649K(14848K), [Metaspace: 3246K->3246K(1056768K)], 0.0061569 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[B@330bedb4
5
循环结束:5
null
null
null
null
[B@330bedb4
HeapPSYoungGen      total 6144K, used 4377K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)eden space 5632K, 77% used [0x00000000ff980000,0x00000000ffdc6790,0x00000000fff00000)from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)ParOldGen       total 8704K, used 649K [0x00000000fec00000, 0x00000000ff480000, 0x00000000ff980000)object space 8704K, 7% used [0x00000000fec00000,0x00000000feca27d0,0x00000000ff480000)Metaspace       used 3253K, capacity 4500K, committed 4864K, reserved 1056768Kclass space    used 352K, capacity 388K, committed 512K, reserved 1048576K

解决前面为null的问题,目的是将软引用本身也回收掉,结合引用队列实现

/*** 演示软引用, 配合引用队列*/
public class Demo2_4 {private static final int _4MB = 4 * 1024 * 1024;public static void main(String[] args) {List<SoftReference<byte[]>> list = new ArrayList<>();// 引用队列ReferenceQueue<byte[]> queue = new ReferenceQueue<>();for (int i = 0; i < 5; i++) {// 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);System.out.println(ref.get());list.add(ref);System.out.println(list.size());}// 从队列中获取无用的 软引用对象,并移除Reference<? extends byte[]> poll = queue.poll();while( poll != null) {list.remove(poll);poll = queue.poll();}System.out.println("===========================");for (SoftReference<byte[]> reference : list) {System.out.println(reference.get());}}
}
输出:
[B@7f31245a
1
[B@6d6f6e28
2
[B@135fbaa4
3
[B@45ee12a7
4
[B@330bedb4
5
===========================
[B@330bedb4//就只有一个了

演示弱引用

/*** 演示弱引用* -Xmx20m -XX:+PrintGCDetails -verbose:gc*/
public class Demo2_5 {private static final int _4MB = 4 * 1024 * 1024;public static void main(String[] args) {//  list --> WeakReference --> byte[]List<WeakReference<byte[]>> list = new ArrayList<>();for (int i = 0; i < 5; i++) {// 5 10 WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);list.add(ref);for (WeakReference<byte[]> w : list) {System.out.print(w.get()+" ");}System.out.println();}System.out.println("循环结束:" + list.size());}
}输出:
[B@7f31245a
[B@7f31245a [B@6d6f6e28
[B@7f31245a [B@6d6f6e28 [B@135fbaa4
[GC (Allocation Failure) [PSYoungGen: 1941K->504K(6144K)] 14229K->13031K(19968K), 0.0013037 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[B@7f31245a [B@6d6f6e28 [B@135fbaa4 [B@45ee12a7
[GC (Allocation Failure) [PSYoungGen: 4712K->504K(6144K)] 17239K->13031K(19968K), 0.0142184 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
[B@7f31245a [B@6d6f6e28 [B@135fbaa4 null [B@330bedb4
循环结束:5
HeapPSYoungGen      total 6144K, used 4769K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)eden space 5632K, 75% used [0x00000000ff980000,0x00000000ffdaa518,0x00000000fff00000)from space 512K, 98% used [0x00000000fff80000,0x00000000ffffe030,0x0000000100000000)to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)ParOldGen       total 13824K, used 12527K [0x00000000fec00000, 0x00000000ff980000, 0x00000000ff980000)object space 13824K, 90% used [0x00000000fec00000,0x00000000ff83bc70,0x00000000ff980000)Metaspace       used 3250K, capacity 4500K, committed 4864K, reserved 1056768Kclass space    used 352K, capacity 388K, committed 512K, reserved 1048576K

当上面循环10次时测试:

2. 垃圾回收算法

2.1 标记清除
定义: Mark Sweep

  • 速度较快
  • 会造成内存碎片

    2.2 标记整理
    定义:Mark Compact
  • 速度慢
  • 没有内存碎片

2.3 复制
定义:Copy

  • 不会有内存碎片
  • 需要占用双倍内存空间

3. 分代垃圾回收

  • 对象首先分配在伊甸园区域
  • 新生代空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy算法 复制到 to 中,存活的对象年龄加1, 并且交换 from to
  • minor gc 会引发 stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行
  • 当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit),保存在对象头中
  • 当老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发 full gc,STW的时间更长

3.1 相关 VM 参数

演示内存的分配策略

/***  演示内存的分配策略*/
public class Demo2_1 {private static final int _512KB = 512 * 1024;private static final int _1MB = 1024 * 1024;private static final int _6MB = 6 * 1024 * 1024;private static final int _7MB = 7 * 1024 * 1024;private static final int _8MB = 8 * 1024 * 1024;// 堆初始大小 堆最大大小  新生代大小// -Xms20M   -Xmx20M     -Xmn10M    -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:-ScavengeBeforeFullGCpublic static void main(String[] args) throws InterruptedException {//        new Thread(() -> {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_8MB]);list.add(new byte[_8MB]);
//        }).start();System.out.println("sleep....");Thread.sleep(1000L);}
}输出:DefNew新生代:2049K回收前->679K回收后 9216K这个区的总内存
[GC (Allocation Failure) [DefNew: 2049K->679K(9216K), 0.0016110 secs][Tenured: 8192K->8870K(10240K), 0.0024582 secs] 10241K->8870K(19456K), [Metaspace: 3239K->3239K(1056768K)], 0.0041324 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 8870K->8851K(10240K), 0.0020503 secs] 8870K->8851K(19456K), [Metaspace: 3239K->3239K(1056768K)], 0.0020788 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceHeapdef new generation   total 9216K, used 246K [0x00000000fec00000内存地址, 0x00000000ff600000, 0x00000000ff600000)eden space 8192K,   3% used [0x00000000fec00000, 0x00000000fec3d890, 0x00000000ff400000)from space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)tenured generation   total 10240K, used 8851K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)the space 10240K,  86% used [0x00000000ff600000, 0x00000000ffea4fd0, 0x00000000ffea5000, 0x0000000100000000)Metaspace       used 3271K, capacity 4496K, committed 4864K, reserved 1056768Kclass space    used 355K, capacity 388K, committed 512K, reserved 1048576K当在mian线程创建子线程执行任务时,发生fullgc时不会导致jvm的退出

4. 垃圾回收器

分类:单线程(串行),多线程(吞吐量优先,响应时间优先)

1. 串行

  • 单线程
  • 堆内存较小,适合个人电脑

2. 吞吐量优先

  • 多线程
  • 堆内存较大,多核 cpu
  • 让单位时间内,STW 的时间最短 0.2 0.2 = 0.4,垃圾回收时间占比最低,这样就称吞吐量高,每次0.2,一小时2次

3. 响应时间优先

  • 多线程
  • 堆内存较大,多核 cpu
  • 尽可能让单次 STW 的时间最短 0.1 0.1 0.1 0.1 0.1 = 0.5 每次0.1,一小时5次

GC垃圾收集器

4.1 串行

SerialGC 2个

-XX:+UseSerialGC = Serial(新生代,复制算法)** + SerialOld**(老年代,标记整理)
对象的内存地址需要改变,程序需要安全的使用这些对象的地址,所以需要到达安全点停下来

4.2 吞吐量优先

ParallelGC 2个 并行的
-XX:+UseParallelGC(新生代,复制算法) ~ -XX:+UseParallelOldGC(老年代,标记整理) jdk1.8默认的,这2个参数开启一个另一个会自动开启

-XX:+UseAdaptiveSizePolicy 采用对新生代自适应的内存大小,运行会动态的调整;开关打开,动态的调整eden和survive之间的比例

-XX:GCTimeRatio=ratio 垃圾回收时间和总时间的占比 (1/1+ratio),达不到会扩容heap的大小来达到设置的参数目的;目标:调整垃圾回收时间和总时间的占比,ratio=99默认值,该参数的意思是垃圾回收时间不能超过总时间的1%,100分钟最多有1min垃圾回收,达不到这个目标会动态的调整堆的大小来达到这个目标,堆调整大了发生GC的时间就不怎么频繁了,要求就达到了。

-XX:MaxGCPauseMillis=ms stw暂停的最大时间,默认是200ms,一般和上一个参数是冲突的,扩大了堆内存那么垃圾回收时间就会变长了

-XX:ParallelGCThreads=n 设置并行运行的gc线程数,默认是cpu核数相同的,cpu全在做垃圾回收,这时cpu使用会飙升

4.3 响应时间优先

CMS 3个 并发的

-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld
说明:
CMS并发的标记清除收集器,在老年代使用;通常配合的UseParNewGC使用,UseParNewGC在新生代的复制算法的垃圾收集器,它两是一对。但是当CMS发生并发失败的问题,他就会采取一个补救的措施,让老年代CMS并发收集器变为单线程的SerialOld垃圾收集器。CMS标记清除当碎片过多会退化为SerialOld老年代的垃圾收集器

-XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads
说明:
ParallelGCThreads 并行的垃圾收集线程数,一般和cpu核数一样;
ConcGCThreads 并发的核心线程数,一般设置为并行线程数的1/4,占用了cpu,所以对吞吐量是有一定影响的。本来4个用户线程干活,现在3个用户线程了

-XX:CMSInitiatingOccupancyFraction=percent
说明:
何时来进行CMS垃圾回收的内存占比,比如为80,表示当老年代使用率达到80%就会发生垃圾回收;这样是为了预留一些空间给那些浮动垃圾,CMS并发清理,所有会产生浮动垃圾,浮动垃圾就是在cms工作的同时用户线程工作而产生的垃圾

-XX:+CMSScavengeBeforeRemark
说明:
考虑到有可能新生代的对象引用老年代的对象,所以在重新标记之前做一个年轻代垃圾回收,否则需要扫描整个堆,重新标记的代价就比较大了; +就是打开,-就是禁用;在做重现标记之前对新生代做个垃圾回收,做完在重新标记的扫描压力也就小了

并发:用户线程和垃圾收集线程并发执行。
并行:垃圾收集线程工作时用户线程是不能工作。

初始化标记是stw的,很快,只标记根对象,GCRoot对象,之后用户线程就可以执行了,垃圾线程和用户线程并发执行的,重新标记也是stw,因为在并发标记可能会产生一些新引用,重新标记完了就可以并发清理了,并发执行,所以是响应时间优先的垃圾收集器;

因为并发清理会产生一些浮动垃圾,在要等到下次GC才会被回收,所以要预留内存给浮动垃圾

4.4 G1


定义:Garbage First

  • 2004 论文发布
  • 2009 JDK 6u14 体验
  • 2012 JDK 7u4 官方支持
  • 2017 JDK 9 默认

适用场景

  • 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms
  • 超大堆内存,会将堆划分为多个大小相等的Region
  • 整体上是标记+整理算法,两个区域之间是复制算法

相关 JVM 参数
-XX:+UseG1GC 开关启用,jdk9默认了
-XX:G1HeapRegionSize=size 1 2 4 8M 这样的大小
-XX:MaxGCPauseMillis=time

1) G1 垃圾回收阶段

对新生代的收集—>新生代的收集+并发的标记----->混合收集(E,S,O 区) 3个阶段是循环的

2) Young Collection

复制算法拷贝到幸存区: 新生代会stw

工作一段时间,当幸存区比较多了,幸存区内对象移动一次该对象年龄+1,达到年龄会进入老年代:

3) Young Collection + CM

  • 在 Young GC 时会进行 GC Root 的初始标记
  • 老年代占用堆空间比例达到阈值时,进行并发标记(不会 STW),由下面的 JVM 参数决定 -XX:InitiatingHeapOccupancyPercent=percent(默认45%)

    4) Mixed Collection
    会对 E、S、O 进行全面垃圾回收
  • 最终标记(Remark)会 STW
  • 拷贝存活(Evacuation)会 STW
    -XX:MaxGCPauseMillis=ms 设置stw的时间

    E的幸存对象会用复制算法复制到S区,另一些符合年龄的也会复制到S区,当然还有一些年龄达到阀值的会晋升到O老年代区,这些是属于新生代的回收,这里发生在混合收集阶段,还有一部分老年代的对象,经过了并发标记阶段,有些对象标记了就会复制到别的O老年代区,考虑到 XX:MaxGCPauseMillis 参数的配置,jvm会根据最大暂停时间有选择的进行某一些O老年代进行有选择的回收,选出回收价值最高的O区进行垃圾回收达到最大暂停时间的设置。这就是G1名字的由来了

5) Full GC

  • SerialGC

    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • ParallelGC
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • CMS
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足
  • G1
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足: 并发收集阶段,回收收集速度低于垃圾产生的速度会发生Full GC

6) Young Collection 跨代引用

新生代回收

  • 新生代回收的跨代引用(老年代引用新生代)问题:找到根对象,可达性分析找到存活对象,存活对象进行复制,复制到幸存区;根对象一般来自老年代的,老年代对象一般很多,如果遍历整个老年代效率是比较低的,因此用了卡表的技术;引用了新生代就标记为脏卡,这样就在GC遍历的时候就不要遍历整个老年代了,关注脏卡对象就可以了,提高扫描根对象的效率;

  • 卡表与RememberedSet:新生代这边会记录RS,从外部对我的一些引用,提高找GCRoot对象的时间

  • 在引用变更时通过 post-writebarrier + dirtycardqueue

  • concurrentrefinementthreads更新RememberedSet


7) Remark


5.垃圾回收调优

掌握 GC 相关的 VM 参数,会基本的空间调整
掌握相关工具
明白一点:调优跟应用、环境有关,没有放之四海而皆准的法则

5.1 调优领域

  • 内存
  • 锁竞争
  • cpu 占用
  • io
  • GC参数

5.2 确定目标

  • 【低延迟】还是【高吞吐量】,选择合适的回收器
  • CMS,G1,ZGC
  • ParallelGC
  • Zing

5.3 最快的 GC
答案是不发生 GC
查看 FullGC 前后的内存占用,考虑下面几个问题

  • 数据是不是太多?
  • 数据表示是否太臃肿?
    • 对象图; 查数据库查需要的数据,不要一把抓
    • 对象大小 16 Integer 24 int 4 对象的瘦身,能用int不用Integer
  • 是否存在内存泄漏?
    • 软引用
    • 弱引用
    • 第三方缓存实现

5.4 新生代调优

  • 新生代的特点

    • 所有的 new 操作的内存分配非常廉价

      • TLAB thread-local allocation buffer
    • 死亡对象的回收代价是零
    • 大部分对象用过即死
    • Minor GC 的时间远远低于 Full GC
  • 越大越好吗?
    -XmnSets the initial and maximum size (in bytes) of the heap for the young generation (nursery).GC is performed in this region more often than in other regions. If the size for the younggeneration is too small, then a lot of minor garbage collections are performed. If the size is toolarge, then only full garbage collections are performed, which can take a long time to complete.Oracle recommends that you keep the size for the young generation greater than 25% and lessthan 50% of the overall heap size.

  • 新生代能容纳所有【并发量 * (请求-响应)】的数据

  • 幸存区大到能保留【当前活跃对象+需要晋升对象】

  • 晋升阈值配置得当,让长时间存活对象尽快晋升;-XX:MaxTenuringThreshold=threshold -XX:+PrintTenuringDistribution

5.5 老年代调优

以 CMS 为例

  • CMS 的老年代内存越大越好,防止浮动垃圾多导致退化为SerialOld老年代的垃圾收集器
  • 先尝试不做调优,如果没有 Full GC 那么已经…,否则先尝试调优新生代
  • 观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
    • -XX:CMSInitiatingOccupancyFraction=percent 老年代内存占比达到就触发gc

5.6 案例

  • 案例1 Full GC 和 Minor GC频繁
  • 案例2 请求高峰期发生 Full GC,单次暂停时间特别长(CMS)
  • 案例3 老年代充裕情况下,发生 Full GC (CMS jdk1.7)

JVM----②垃圾回收相关推荐

  1. 老李分享:jvm垃圾回收

    老李分享:jvm垃圾回收 1.垃圾收集算法核心思想 java语言建立了垃圾回收机制,用于跟踪正在被使用(引用)的对象和没有被使用(引用)的对象,该机制可以有效防范动态内存分配中可能发生的两个危险:因垃 ...

  2. JVM垃圾回收算法 总结及汇总

    先看一眼JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:jvm如何知道那些对象需要回 ...

  3. JVM 垃圾回收算法 -可达性分析算法!!!高频面试!!!

    前言:学习JVM,那么不可避免的要去了解JVM相关的垃圾回收算法,本文只是讲了讲了可达性分析算法,至于标记-清除.标记-复制,标记-整理,分代收集等等算法,会在近两天的文章中陆续更新出来. 很喜欢一句 ...

  4. java学习笔记-4 JVM垃圾回收(GC)

    引言 jvm垃圾回收相关的问题是老生常谈的问题了,相信大家都有所了解,这里再进行相关的探讨,以加深理解.若文中有不正之言,望不吝指正. 本文将围绕以下几个点展开 1.为什么要进行垃圾回收 我们知道jv ...

  5. jvm - 垃圾回收 gc

    2019独角兽企业重金招聘Python工程师标准>>> jvm - 垃圾回收 注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注 垃圾回收 ...

  6. 4、JVM垃圾回收机制、新生代的GC、GC(Minor GC、FullGC)、GC日志、JVM参数选项、元空间(笔记)

    4.JVM垃圾回收机制 4.1.新生代的GC 4.1.1.串行GC(SerialGC) 4.1.2.并行回收GC(Parallel Scavenge) 4.1.3.并行GC(ParNew) 4.2.G ...

  7. jvm垃圾回收机制_JVM 垃圾回收机制之堆的分代回收

    JVM垃圾回收机制之堆的分代回收 前言 前文我们了解了Java的GC机制,对于堆中的对象,JVM采用引用计数和可达性分析两种算法来标记对象是否可以清除,本文中我们还会了解到JVM将对分成了不同的区域, ...

  8. 垃圾回收机制和JVM垃圾回收常见算法

    垃圾回收机制和JVM垃圾回收常见算法 垃圾回收的好处和特点: 好处: 1. 提高编程效率: 2. 垃圾回收机制保护程序的完整性. 特点: 1. 只能回收无用对象的内存空间,对其他物理资源无能为力: 2 ...

  9. jvm gc垃圾回收机制和参数说明amp;amp;Java JVM 垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

    jvm gc(垃圾回收机制) Java JVM  垃圾回收(GC 在什么时候,对什么东西,做了什么事情) 前言:(先大概了解一下整个过程) 作者:知乎用户 链接:https://www.zhihu.c ...

  10. 关于JVM垃圾回收的几个问题

    本文来说下关于JVM垃圾回收的几个问题 文章目录 判断对象是否可回收有几种方式 "GC Roots"对象都包含哪些 Java四种引用类型分别是什么 Java四种引用使用场景 JVM ...

最新文章

  1. linux一个网卡绑定多个端口,RedHat实现多网卡绑定
  2. websphere安装应用失败_如何使用安卓手机给任天堂Switch安装游戏NSUSBloader mobile
  3. 项目托管至GitHub上
  4. 分享一些优秀有趣的博客
  5. jooq sql_使用jOOQ和JavaFX将SQL数据转换为图表
  6. mysql大表数据抽取_从云数据迁移服务看MySQL大表抽取模式
  7. 中国的顶级黑客-小榕
  8. Electron 设置透明窗口transparent 属性win7无效详解
  9. python 单位根检验代码_Python中ADF单位根检验实现查看结果的方法
  10. centos虚拟机上网慢的问题
  11. 电脑键盘指法的正确练习步骤
  12. [HttpServlet] Error occured when handling uri: /cat/s/router
  13. 前端学习路线(个人愚见)
  14. DMB DSB和ISB区别
  15. BigDecimal
  16. excel服务器okr系统,OKR工具能帮企业落地OKR吗?从飞书OKR看专业工具的价值
  17. PTA 6-1 舞伴问题
  18. 计算机主机配置有哪些,组装电脑配置推荐有哪些
  19. docker-compose概述与简单编排部署
  20. 年后跳槽那点事:乐视+金山+360面试之行

热门文章

  1. 东北林业大学计算机第三轮学科评估,全国第三轮学科评估结果.PDF
  2. MIUI开发版内测申请地址
  3. flex 电子表格实现
  4. JSP+ssm计算机毕业设计律师事务所管理系统703n5【源码、数据库、LW、部署】
  5. 2011考研英语单词记忆的15个方法总结
  6. RDS认证标准,申请RDS时供应商如果没有有这样的认证企业该如何做
  7. 从中建三局 “安康杯”安全知识竞赛看竞赛软件的魔力
  8. 用python做数据透视表
  9. 跟一位知名亿万富豪大佬聊天后,我的5点感悟!
  10. 培养和锻炼语言表达能力