JVM知识点的整理

1、JVM的重要组成部分

1、类加载器
Java转换字节码
2、运行时数据区
把字节码加载到内存中
3、执行引擎
将字节码转换成为操作系统指令,交由CPU执行
4、本地库接口
执行过程可能调用其他语言的本地库接口
在这里插入图片描述

2、类的加载过程

1、加载(根据路径加载文件)
2、检查(检查文件是否正确)
3、准备
准备给类的静态变量在堆内分配内存空间,静态变量只初始化一次
4、**解析:**将常量池中的符号引用替换成直接引用,符号引用一个标识,直接引用可以理解为直接指向内存中的地址,常量池在元空间
5、初始化对静态变量和静态代码块进行初始化
在这里插入图片描述

3、双亲委派机制删除线格式

在这里插入图片描述

双亲委派机制就是,加载一个类,会现获取到类的系统类加载器,层层网上,先是应用类加载器(Application ClassLoader),然后拓展类加载器(Extension ClassLoader),最后还是启动类加载器(Bootstrap ClassLoader),会有系统类加载,从上面的启动类开始加载,如果没有就层层往下,如果都没有就报错

4、运行时数据区

在这里插入图片描述
在这里插入图片描述

  1. JVM虚拟机栈

    存储局部操作数栈,方法出口等,为每个被执行的方法创建一个栈帧,线程私有这点跟堆是不同的。

  2. java堆

    内存最大的一块,多有new的对象都在这里分配内存,被所有线程共享

  3. 程序计数器

    保存字节码行号。

  4. 方法区

    存储类信息,常量,静态变量,即编译的代码数据。

  5. 本地方法栈

    服务虚拟机调用本地方法,

5、垃圾回收机制

1、什么是垃圾回收?
垃圾回收就是,回收那些死亡对象所占据的堆空间
2、如何判断一个对象是垃圾
**引述计数法:**需要额外的空间存储数据,如果一个引用指向某一个对象,则改该对象的引用计数器+1,如果该引用指向另一个对象,则原先的对象计数器+1
但这种算法,回存在循环引用的bug问题,存在内存溢出的风险 。
可达性分析法是以GC Root作为起点,能够引用到的对象则是有用对象,反之,则是死亡的,
什么是GC Root,一般理解为对外指向堆内的引用,包裹以下常见的两种,
1、java方法栈帧中的局部变量
2、已被加载的类静态变量
(1)虚拟机(JVM)栈中引用对象

(2)方法区中的类静态属性引用对象

(3)方法区中常量引用的对象(final 的常量值)

(4)本地方法栈JNI的引用对象

2、垃圾回收算法**

  1. 标记清除算法

    是现在垃圾算法的思想基础,它将垃圾回收分为两个阶段:

    标记阶段和清除阶段。

    首先是通过根节点GC Root,标记所有从根节点开始的可达对象

    因此未被标记的对象都是垃圾对象

    然后在清除阶段,则删除所有未被标记的对象

    preview

    preview

标记清楚算法的缺点:

  1. 效率不高
  2. 该算法会产生不连续的内存碎片,当我们需要分配较大对象时 ,因为无法找到足够的连续内存空间,而不得不再次提前出发垃圾回收,如果内存还是不够,则报内存不足异常。

标记压缩算法**

标记压缩算法是老年代的一种回收算法,

首先,标记阶段跟"标记清楚算法"一致

区别在于清理阶段,为了避免内存碎片产生,所有的对象会被压缩到内存的一端

preview

preview

这个算法解决之前标记清除算法的碎片问题

但是标记和压缩的效率依然不高

3、复制算法**

复制算法是为了解决效率问题,他们将内存一分为二,每次只是用其中一块

这样,当一块内容用完了,就将内存的对象复制到另一块内存一次清理掉,这样回收的效率提高,也不存在内存碎片的的问题。

preview

preview

算法优点是回收效率高,不存在内存碎片,但是浪费一半的内存空间,另外在对象存货效率高的情况下, 采用复制算法,效率将会降低。

4、分代收集法

目前,主流的虚拟机大都采用分代收集算法,它根据对象存货周期不同,而将内存划分多块区域,一般是我们耳熟能详的新生代和老生带,然后采用不同的回收算法。
新年代(Eden),对象的存活率低,所以采用复制算法。
老年代(Old),对象的存活率高,所以采用标记清除算法或标记整理算法。
对象优先分配到新生代,如果长期存活或者对象过大会直接分配到老年代(新生)

算法细节:

  1. 对象新建,将存放在新生代的Eden区域,注意Suvivor(幸存者)又分为两个区域,FromSuv和ToSuv,分配为8:1:1

    preview

  2. 当年轻的Eden满时,将会触发MinorGC ,如果对象依然存活,对象将会被转移到FromSuvivor空间,对象还是在新生代

    preview

  3. 再次发生 minor GC,对象还存活,那么将会采用复制的算法,将对象转移到ToSuvivor,此时对象的年龄+1

    preview

  4. 再次发生minor GC,对象依然存活,此时Survivor中跟对象Object同龄的对象还没到达Survivor区一半,所以还是会采用复制算法,将fromSuv和ToSuv的区域进行交换

    preview

  5. 当防身多次Minor GC,对象Object仍然存活,且此时,此时Suvivor中跟对象OBject同龄的对象达到Survivor的一半,name对象Object将会移动到老年带区域,或者对像经过多次回收,年龄达到了15岁,那么也会迁移到老年代

    preview

    元空间

    JDK1.8之前叫永久代,和老年区捆绑在一块,无论谁满了,都会触发永久代和老年代的垃圾回收。存放类信息、常量、静态变量,即编译器编译后的代码。

    元空间中,每个加载器都有单独的存储空间,类和其元数据的生命周期与其对应的类加载器相同,省略掉了GC扫描及压缩的的时间,当GC发现某个类加载器不再存活了,会把对应的空间整个回收。

5**、JVM配置的相关参数**

  • Xms2g;初始化堆大小为2g
  • Xmx4g:堆内存大小为4g
  • XX:NewRatio=4 :设置年轻的和老年代的内存比例为1:4;
  • XX:SurvivorRatio=8:设置新生代Eden和Survivor比例为8:2;

6、垃圾回收器有哪些?

垃圾回收的时候,都有一个统一的的特点,叫stop the

world

往回收率越来越高的方向来走的,垃圾回收的时间(stop the

wrold)时间在变短

  1. 单线程回收器

    采用多线程回收,效率一般,服务器是多核CPU资源无法得到更好的利用

  2. 多线程回收器

    可以充分利用CPU资源

  3. CMS回收器

    3.1初始化标记

    GCRoot

    public class Gc{
          private static SomeObject = new SomeObject();
    }
    
    class SomeObject{
          
    }
    

    个时候会stop the world,但是由于我们只是标记GCRoot,所以花费的时间很短

    3.2、并发标记

    一遍可以继续往下跟踪,做可达性分析,相比比较耗时100

    一遍可以让程序继续运行,可能重新创建对象,叶铿能制造垃圾20

    3.3、重新标记

    出处理在并发标记过程中,再次产生的垃圾, stop the world 20

    3.4并发回收

    一遍针对为我们刚才的垃圾对象进行回收

    一遍程序继续运行

  4. G1垃圾回收器

    将内存划分多个块 ,每个块再独立进行回收

6、堆和栈

堆(heap)栈(stack)
存储是随意的后进先出
程序员分配释放空间操作系统释放空间
动态申请空间大空间小
保存方法中的参数值,局部变量存放new出来的具体实例
对所有线程可见归属于单个线程,每个线程都会有宇哥栈内存,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值