详细画的jvm模型图
https://www.processon.com/diagraming/64c8aa11c07d99075d934311
官方网址
https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
相关概念
-
年轻代是所有新对象被分配和老化的地方。当年轻代填满时,这会导致minor garbage collection,minor gc会回收掉很多的游离对象。游离的年轻代很快就被收集起来。一些幸存的最终转移到老年代。
-
Stop the World Event(STW),所有minor gc都是STW。这意味着所有应用程序线程都将停止,直到操作完成。
-
老年代用于存储长期存活的对象。通常,为年轻代对象设置阈值,当达到该年龄时,对象将移动到老年代。最终需要回收老年代。此事件称为major garbage collection。
-
major gc也会触发STW。通常,major gc会更慢,因为它涉及所有活动对象。因此,对于响应式应用程序,应尽量减少major gc。
分代垃圾回收过程:
1.首先,任何新对象都被分配到eden区。两个幸存区一开始都是空的。
2.当eden区填满时,将触发minor gc
3.引用的对象将移动到S0。清除eden,将删除未引用的对象。
4.在下一个minorGC中,eden也会发生同样的事情。未引用的对象将被删除,引用的对象将移动到幸存者区。但是,在这种情况下,它们被移动到第二个幸存者区 (S1)。此外,来自第一个幸存者区 (S0) 上最后一次minor GC 的对象会增加其年龄并移动到 S1。一旦所有幸存的物体都被移动到S1,S0和Eden都会被清除。请注意,我们现在在幸存者区s1中有不同年龄age的对象
5.在下一次minor GC 中,重复相同的过程。然而,这一次幸存者空间切换了。引用的对象将移动到 S0。幸存的对象会老化age+1。eden和S1被清除。
6.这里为了演示,当年龄对象达到一定的年龄阈值(在本例中为 8)时,它们将从新生代晋升为老年代
7.随着minor GC 的继续出现,对象将继续提升到老年代
8.这几乎涵盖了年轻代的整个过程。最终,将对老年代进行major GC,以清理和压缩该空间
常用的设置项
设置项 | 描述 |
---|---|
-Xms | Sets the initial heap size for when the JVM starts. 设置 JVM 启动时的初始堆大小 |
-Xmx | Sets the maximum heap size.设置堆最大值 |
-Xmn | Sets the size of the Young Generation.设置年轻代最大值 |
-XX:PermSize | Sets the starting size of the Permanent Generation.设置永久代的起始值 |
-XX:MaxPermSize | Sets the maximum size of the Permanent Generation设置永久代的最大值 |
案例:下面是一个简单的开始Java2Demo的例子:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
java垃圾回收算法
1.标记-清除法:通过gc root 标记所有被程序引用的对象,然后清理没有被标记的对象。总共分为两个阶段:标记和清除
缺点:
1.效率较低,标记和清除两个动作都需要遍历所有对象,并且在GC时,都需要暂停应用程序,对于交互性比较要求比较高的应用而言这种体验非常差
2.会产生内存碎片,通过标记清除法清理出来的内存碎片化较为严重,因为被清理的对象存在于内存的各个角落,所以清理出来的内存不是连贯的
2.标记-整理法:是在标记清除法的基础上进行了优化,和上面的一种算法标记阶段是一样的,不同的是在清除阶段,不是简单的清除未标记的对象,而是将所有的已经标记的存活对象移向一端,然后清除该端以为的所有内存。
缺点:解决了标记清除法碎片化问题,同时多了整理的这一步,对象移动内存位置的步骤,其效率有一定的影响
3.复制算法:这是一种将内存空间分为两个部分的垃圾回收算法,通常称为“From”空间和“To”空间。在分配内存时,对象会被分配到From空间。当From空间占满一定比例时,触发垃圾回收过程。垃圾回收器会遍历From空间,将存活的对象复制到To空间,并按照顺序排列。然后,回收整个From空间,将其标记为空闲的内存,然后将From空间和To空间交换角色
缺点:如果内存中的垃圾对象较多,需要复制的对象少,这种情况下使用这个算法比较合适效率较高,反之,不合适。
垃圾回收器的分类
分类方式:按线程数分、按照工作模式分、按碎片处理方式分、按工作的内存区间分
按线程数分
- 可以分为串行垃圾回收器(Serial Collector)和并行垃圾回收器(Parallel Collector)。
- 串行回收指的是在同一时间段内只允许有一个 CPU 用于执行垃圾回收操作,此时工作线程被暂停,直至垃圾收集工作结束。
- 和串行回收相反,并行收集可以运用多个 CPU 同时执行垃圾回收,因此提升了应用的吞吐量,不过并行回收仍然与串行回收一样,采用独占式,使用了 STW 机制。
按照工作模式分
- 可以分为并发式垃圾回收器和独占式垃圾回收器。
- 并发式垃圾回收器与应用程序线程交替工作,以尽可能减少应用程序的停顿时间。
- 独占式垃圾回收器一旦运行,就停止应用程序中的所有用于线程,直到垃圾回收过程完全结束。
按碎片处理方式分
- 可以分为压缩式垃圾回收器和非压缩式垃圾回收器。
- 压缩式垃圾回收器会在回收完成后,对存活对象进行压缩整理,消除回收后的碎片。(再分配对象空间使用指针碰撞)
- 非压缩式的垃圾回收器不进行这步操作。(再分配对象空间使用空闲列表)
按工作的内存区间分
- 又可分为年轻代垃圾回收器和老年代垃圾回收器
设置案例
串行回收器
要启用串行回收器(Serial Collector)使用,请执行以下操作:
-XX:+UseSerialGC
下面是用于启动Java2Demo的示例命令行:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
并行回收器
也称为吞吐量回收器。因为它可以使用多个 CPU 来加快应用程序吞吐量。当需要完成大量工作并且可以接受长时间暂停时,应使用此回收器。例如,批处理,如打印报表或帐单,或执行大量数据库查询。
-XX:+UseParallelGC
使用此命令行选项,您将获得具有单线程老年代回收器的多线程年轻代回收器。该选项还执行老年代代的单线程压缩。
下面是用于启动Java2Demo的示例命令行:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
-XX:+UseParallelOldGC
通过该选项,GC 既是多线程年轻代回收器,又是多线程老年代收集器。它也是一个多线程压缩收集器。HotSpot仅在老一代中进行压缩。热点中的年轻一代被认为是复制家;因此,不需要压缩。
压缩描述了以对象之间没有孔的方式移动对象的行为。垃圾回收扫描后,活动对象之间可能会留下孔洞。压实会移动对象,以便没有剩余的孔。垃圾回收器可能是非压缩收集器。因此,并行收集器和并行压缩收集器之间的区别可能是后者在垃圾回收扫描后压缩空间。前者不会。
下面是用于启动 的示例命令行:Java2Demo
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelOldGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
并发标记扫描 (CMS) 回收器
并发标记扫描 (CMS) 回收器(也称为并发低暂停回收器)。它尝试通过与应用程序线程同时执行大部分垃圾回收工作来最大程度地减少由于垃圾回收而导致的暂停。通常,并发低暂停回收器不会复制或压缩活动对象。垃圾回收是在不移动活动对象的情况下完成的。如果碎片成为问题,请分配更大的堆。
注意:年轻代的CMS回收器使用与并行回收器相同的算法。
要启用 CMS 回收器,请使用:
-XX:+UseConcMarkSweepGC
并设置线程数,请使用:
-XX:ParallelCMSThreads=<n>
下面是用于启动Java2Demo的示例命令行:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads=2 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
G1 垃圾收集器
Garbage First 或 G1 垃圾回收器在 Java 7 中可用,旨在作为 CMS 回收器的长期替代品。G1 收集器是一个并行、并发且增量压缩的低暂停垃圾回收器,其布局与前面描述的其他垃圾回收器完全不同。
要启用 G1 收集器,请使用:
-XX:+UseG1GC
下面是用于启动Java2Demo的示例命令行:
java -Xmx12m -Xms3m -XX:+UseG1GC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar