JAVA从入门到放弃

JVM内存模型

2020-03-11  本文已影响0人  chuan_bai

一、jvm内存模型

JVM内存模型.jpg

下面说一下大概的一个流程:

  1. class文件会被类装载子系统装载。
  2. 装载到内存中也就是jvm运行时的数据区。
  3. 当我们运行一个方法的时候会创建一个对应的栈桢,
    栈桢包含了操作数栈、局部变量表、动态链接、方法出口等部分,每执行一个操作,都会在程序计数器中,记录程序下一步要执行的指针地址。
  4. 当方法1执行完后会从方法出口,进入到方法二的栈桢中。
  5. 当声明一个方法的时候,会存到到堆区域。
  6. 方法区是线程共享的里面存的是类的所有字段和方法的字节码如Math类
  7. 执行引擎读取运行时数据区的字节码逐个执行

二、jvm内存结构

三、jvm堆结构

首先介绍一下堆,堆是Java 虚拟机所管理的内存中最大的一块,并且是线程共享的,在虚拟机启动时创建,用于存放对象实例,几乎所有的对象(包括常量池)都在堆上分配内存,当对象无法在该空间申请到内存时就会抛出内存溢出异常,堆分为新生代(1/3堆空间)、老年代(2/3 堆空间)、元空间,元空间在就是jdk1.8以前的永久代,是方法区的实现,直接存在内存中,下面分别对堆的几个区域进行介绍

四、类加载机制

五、GC相关

5.1 垃圾收集算法

  1. 引用计数法
    给对象中添加一个引用计数器,没当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0的对象就认为可以被回收。(这个方法实现简单,效率高,但是目前主流虚拟机没有选择这个算法管理内存,主要原因是很难解决对象之间相互循环引用的问题。)
  2. 可达性分析算法
    以“GC Roots”的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的话,则证明此对象时不可能用的
  3. finalize()方法最终判定对象是否存活
    即使在可达性分析算法中不可达的对象,需要经历再次标记过程才真正宣告一个对象死亡

5.2 垃圾清除算法

  1. 标记清除算法
    算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它是最基础的收集算法,效率也很高,但是会带来两个明显的问题:

    • 效率问题(会遍历内存)
    • 空间问题(标记清除后会产生大量不连续的碎片)


      图片.png
  2. 复制算法
    为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。


    图片.png
  3. 标记整理算法
    为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

图片.png
  1. 分代收集算法
    当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

5.3 垃圾收集器

六、JVM调优相关

JVM调优指标

调优步骤

调优命令

上一篇下一篇

猜你喜欢

热点阅读