小白入门JVM最好教程(记得收藏)

大家好,最近在准备面试,所有整理出来一篇JVM 入门的文章

了解JVM无论是对找工作还是面试都十分有必要的

 首先要了解的是什么是JVM?本质上就是用来运行Java字节码的虚拟机,

学习JVM主要学习,JVM如何对对象进行内存分配和回收

Java源文件在通过编译器之后被编译成相应的.Class文件(字节码文件),.Class文件又被JVM中的解释器编译成机器码在不同的操作系统(Windows、Linux、Mac)上运行。每种操作系统的解释器都是不同的,但基于解释器实现的虚拟机是相同的,这也是Java能够跨平台的原因。

Java虚拟机包括一个类加载器子系统(Class Loader SubSystem)、运行时数据区(Runtime DataArea)、执行引擎和本地接口库(Native Interface Library)。本地接口库通过调用本地方法库(Native MethodLibrary)与操作系统交互,如图所示。

  • 类加载器子系统用于将编译好的.Class文件加载到JVM中;
  • 运行时数据区用于存储在JVM运行过程中产生的数据,包括程序计数器、方法区、本地方法区、虚拟机栈和虚拟机堆;
  • 执行引擎包括即时编译器和垃圾回收器,即时编译器用于将Java字节码编译成具体的机器码,垃圾回收器用于回收在运行过程中不再使用的对象;
  • 本地接口库用于调用操作系统的本地方法库完成具体的指令操作。

研究JVM我们主要研究的是JVM运行时数据区 ,  JVM 运行时数据区分为五部分 , 按照线程私有和线程共享分为两大类
线程私有: 程序计数器  , java虚拟机栈 , 本地方法栈
线程共享: 堆 , 方法区

  • 程序计数器: 当虚拟机执行的是java方法时,指向的是当前线程下虚拟机指令的地址,
              如果该方法执行的是Native方法,则程序计数器的值为空 无OOM 出现的区域
  • java虚拟机栈: 为java方法执行提供服务,描述了java方法的执行过程的内存模型,它在当前栈帧(用来记录方法的执行过程)
                 中存储了局部变量表, 操作数栈 , 动态链接 , 方法出口等信息 , 局部变量表中存储了对象的引用   
  •  本地方法区: 本地方法区和虚拟机栈的作用类似, 区别在于java虚拟机栈是为Java方法执行服务的,
             本地方法栈为 Native方法服务的
  • 堆 : 主要用了存储对象的实例 ,是垃圾回收GC的主要区域,堆内存又可分为新生代(1/3堆空间) , 老年代(2/3堆空间) ,元空间,新生代又可分为Eden区 ,  ServivorFrom区和ServivorTo区 , Eden区默认占8/10新生代
  •  方法区: 用于存储类信息,譬如运行时的常量池,字段,方法数据,以及方法和构造方法的代码,
             包括一些在类和实例初始化和接口初始化时候使用的特殊方法
            

JVM垃圾回收机制GC: 主要进行的是堆内存进行GC,因为堆内存主要存储的是对象的实例 , 那GC回收的是什么对象呢?

回收无任何对象引用的对象占据的内存空间 ,

JVM如何进行对象存活的判断呢? 通过引用计数器和可达性分析来计算出那些对象需要回收

引用计数器法: 由于在Java中如果要操作对象,就必须要调用改对象的引用,所以为每个对象创建一个引用计数器, 当对象调用的时候,引用计数器加1, 对象删除一个引用的时候,引用计数器减一,当引用计数器中的值为0时,则表示该对象没有被引用, 可以被回收.  但是引用计数器法会产生循环引用问题:即两个对象相互引用的时候导致它们会一直存在,而不能被回收. 如图表示Object 对象的循环引用问题

                                    

可达性分析:为了解决引用计数器的循环引用问题, Java还采取了可达性分析来判断对象是否可以被回收,具体做法是定义一些GC Roots 对象, 然后这些GC Roots,作为起点,向下搜索 , 如果在GC Roots和对象之间没有可达路径,则该对象为不可达对象,不可达对象要经过至少两次标记才能判定其是否可以被回收,如果在两次标记后该对象仍然是不可达的,则将被垃圾收集器回收。

 

所以判断对象是否可以被回收一般使用可达性分析

了解了什么对象会被回收虚拟机如何判断回收对象现在就应该需要了解GC回收的算法了~

 

首先更深处的了解JVM堆:

Java中常用的垃圾回收算法有标记清除(Mark-Sweep)、复制(Copying)、标记整理(Mark-Compact)和分代收集(Generational Collecting)这 4种垃圾回收算法

标记清除算法: 分为两个阶段 , 标记和清除,  象首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象,缺点是否该对象是否可以被标记,可以使用上面说到的可达性分析法,标记清除算法是最基础的搜集算法,因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的。它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够 的连续内存而不得不提前触发另一次垃圾收集动作

                           

 

复制算法: 复制算法是为了解决标记清除算法内存碎片化的问题而设计的。复制算法首先将内存划分为两块大小相等的内存区域,即区域 1和区域 2,新生成的对象都被存放在区域 1中,在区域 1内的对象存储满后会对区域1进行一次标记,并将标记后仍然存活的对象全部复制到区域 2中,这时区域 1将不存在任何存活的对象,直接清理整个区域1的内存即可

                   

标记整理算法标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向

一端移动,然后直接清理掉端边界以外的内存,

                                

分代收集算法这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和 老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完 成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。

 

学到这里,可能会受益颇多吧! 那就让我们进一步简单了解一下常见的垃圾回收器吧~

 

七大垃圾回收器

一丶 Serial垃圾收集器:单线程,复制算法

 Serial垃圾收集器基于复制算法实现,它是一个单线程收集器,在它正在进行垃圾收集时,必须暂停其他所有工作线程,直到垃圾收集结束。Serial垃圾收集器采用了复制算法,简单、高效,对于单CPU运行环境来说,没有线程交互开销,可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器是Java虚拟机运行在Client模式下的新生代的默认垃圾收集器。

 

二丶 ParNew垃圾收集器:多线程,复制算法

ParNew垃圾收集器是Serial垃圾收集器的多线程实现,同样采用了复制算法,它采用多线程模式工作,除此之外和Serial收集器几乎一样。ParNew垃圾收集器在垃圾收集过程中会暂停所有其他工作线程,是Java虚拟机运行在Server模式下的新生代的默认垃圾收集器。
 

三丶 Parallel Scavenge垃圾收集器:多线程,复制算法

ParallelScavenge收集器是为提高新生代垃圾收集效率而设计的垃圾收集器,基于多线程复制算法实现,在系统吞吐量上有很大的优化,所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值, 可以更高效地利用CPU尽快完成垃圾回收任务。

 

四丶 Serial Old垃圾收集器:单线程,标记整理算法

Serial Old垃圾收集器是Serial垃圾收集器的老年代实现,同Serial一样采用单线程执行,不同的是,SerialOld针对老年代长生命周期的特点基于标记整理算法实现。SerialOld垃圾收集器是JVM运行在Client模式下的老年代的默认垃圾收集器。
 

五丶 Parallel Old垃圾收集器:多线程,标记整理算法

ParallelOld垃圾收集器采用多线程并发进行垃圾回收,它根据老年代长生命周期的特点,基于多线程的标记整理算法实现。ParallelOld垃圾收集器在设计上优先考虑系统吞吐量,其次考虑停顿时间等因素

 

六丶 CMS垃圾收集器 : 标记清除算法

CMS(Concurrent MarkSweep)垃圾收集器是为老年代设计的垃圾收集器,其主要目的是达到最短的垃圾回收停顿时间,基于线程的标记清除算法实现,以便在多线程并发环境下以最短的垃圾收集停顿时间提高系统的稳定性。

CMS的工作机制相对复杂,垃圾回收过程包含如下4个步骤。
(1)初始标记:只标记和GC Roots直接关联的对象,速度很快,需要暂停所有工作线程。
(2)并发标记:和用户线程一起工作,执行GC Roots跟踪标记过程,不需要暂停工作线程。
(3)重新标记:在并发标记过程中用户线程继续运行,导致在垃圾回收过程中部分对象的状态发生变化,为了确保这部分对象的状                              态正确性,需要对其重新标记并暂停工作线程。
(4)并发清除:和用户线程一起工作,执行清除GC Roots不可达对象的任务,不需要暂停工作线程。
 

七丶 G1垃圾收集器

G1(GarbageFirst)垃圾收集器为了避免全区域垃圾收集引起的系统停顿,将堆内存划分为大小固定的几个独立区域,独立使用这些区域的内存资源并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,在垃圾回收过程中根据系统允许的最长垃圾收集时间,优先回收垃圾最多的区域。G1垃圾收集器通过内存区域独立划分使用和根据不同优先级回收各区域垃圾的机制,确保了G1垃圾收集器在有限时间内获得最高的垃圾收集效率。相对于CMS收集器,G1垃圾收集器两个突出的改进。

◎ 基于标记整理算法,不产生内存碎片。
◎ 可以精确地控制停顿时间,在不牺牲吞吐量的前提下实现短停顿垃圾回收。

 

想要了解更多JVM ,推荐看  深入理解Java虚拟机:JVM高级特性与最佳实践  如需要电子版可主页联系我


那么写到这里,基本入门JVM是够了的,完结撒花!!!

 

 

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值