jvm(内存划分,双亲委派模型,垃圾回收机制)

jvm内存区域划分

堆区:保存程序中创建的所有对象。

Java虚拟机栈(方法调用关系):Java 虚拟机栈的生命周期和线程相同,Java 虚拟机栈描述的是 Java 方法执行的 内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储该线程的方法调用信息和局部变量当方法执行完毕后,Java虚拟机会将该栈帧弹出,并回收栈帧所占用的内存空间。

本地方法区:本地方法栈和虚拟机栈类似,只不过 Java 虚拟机栈是给 JVM 使用的,而本地方法栈是给本地方法使用的(jvm内部用c++实现的代码)。

元数据区(以前叫方法区):方法区的作用:用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 的。

程序计数器:记录当前程序执行到哪个指令了。

重点:

1:掌握不同类型变量在jvm中的存储位置

举例:

2:堆和元数据区在每个进程中只有一份(线程之间共享)

      栈和程序计数器则是每个线程都有一份(线程私有)

类加载过程:

把.class文件加载到内存得到类对象的过程。

包括:加载;验证;准备;解析;初始化    5个过程

1:加载:

在加载 Loading 阶段,Java虚拟机需要完成以下三件事情:

1)通过一个类的全限定名来获取定义此类的二进制字节流。

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

总结:找到.class文件,读取文件内容,生成接口

2:验证

确保Class文件的字节 流中包含的信息符合《Java虚拟机 规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全。

3:准备

给类对象分配内存空间(未初始化过的,内存中的数据全为0,比如静态变量)。

比如有这样的变量:public static int value = 12;

此时value的值也为0.

4:解析

将常量池内的符号引用替换为直接引用的过程

符号引用(Symbolic Reference):在Java虚拟机规范中定义的概念,它是指用来描述被引用的目标的一种符号名称。在Java程序中,符号引用可以是类、接口、字段、方法等的名称。符号引用在编译时和链接时使用,它是一种抽象的引用,不直接指向具体的内存地址或偏移量。

直接引用(Direct Reference):是指直接指向内存地址或偏移量的引用

5:初始化

真正开始执行类中的代码,初始化静态成员,静态代码块,要是有父类对父类进行加载

注意:类加载的触发奉行懒汉策略,不是jvm启动就进行加载,(非必要,不加载)

什么时候出发呢?:

1:创建了这个类的实例

2:使用了类的静态方法/静态属性

3:子类会触发父类的类加载

双亲委派模型

jvm进行类加载时需要用到三层类加载器:

1:Bootstrap ClassLoader(启动类加载器,是虚拟机的一部分,用来加载Java标准库中的一些类)

2:Extension ClassLoader (加载一些非标准库中的但是是sun/Oracle扩展的库的类)

3:Application ClassLoader (加载项目中自己写的类以及第三方库中的类)

具体内容:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类) 时,子加载器才会尝试自己去完成加载。

优点:1:避免重复加载类

           2:保证了安全性(核心类只能使用大佬写好的能保证安全性的类)

jvm垃圾回收机制(GC:Garbage Collection):

Java虚拟机自动管理内存的一种机制。在Java程序运行过程中,对象会被动态地分配到堆内存中,而垃圾回收机制会自动扫描堆内存中的对象,找出不再被程序使用的对象,并将它们回收掉,以释放内存空间供其他对象使用。垃圾回收机制可以有效地避免内存泄漏和内存溢出等问题,使得Java程序的内存管理更加简单和安全。

具体来说,GC是释放jvm那一部分内容呢?栈区和程序计数器会随着线程的结束自动被释放,元数据区自然也不用释放,所以GC主要释放空间的区域是 堆区,即释放对象。

GC主要分为俩个阶段:

1:找垃圾

2:释放垃圾

找垃圾:

原则:什么样的对象被认为是垃圾?     一个对象,如果后续不再被使用就被认为是垃圾

不被使用分俩种情况:1.对象没有引用了,它就再也无法被使用,自然就被当做垃圾回收了。

                                    2.对象的引用还在,但是我们不对其进行使用了。

这里我们讲的垃圾确定策略针对第二种情况:

找垃圾策略:

1.引用计数

给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已"死"。python就是用这种策略。

缺点:1:浪费内存空间(引入一个额外的空间进行计数)

           2:循环引用是无法争取判断:(Java不使用引用计数策略的原因)

2.可达性分析(Java使用的策略):

通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索 走过的路径称之为"引用链",当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象 不可达)时,证明此对象是不可用的。

什么样的对象可以作为"GC Roots“对象?

1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;

2. 方法区中类静态属性引用的对象;

3. 方法区中常量引用的对象;

4. 本地方法栈中 JNI(Native方法)引用的对象。

简要来说,就是从gcroots出发,把所有能访问到的对象访问一遍同时标记为”可达的“,自然剩下的未被标记的对象就是”垃圾“了。

缺点:

可达性分析解决了引用计数的俩个缺点,但是又产生了新的问题:

1:消耗更多的时间(扫描过程需要时间)

2:如果在扫描过程中,对象的引用关系发生了变化,就不能被发现。

因此,为了让结果更加准确,在扫描过程中需要让业务暂停(STW问题)

STW(Stop-The-World)问题是指在进行垃圾回收时,Java虚拟机会暂停所有的应用线程,以便进行垃圾回收操作。这个暂停时间称为STW时间,期间应用线程无法继续执行任何任务。

STW问题可能会对系统的响应性和性能造成影响。当垃圾回收器运行时,所有的应用线程都会被暂停,这意味着系统无法响应用户请求或处理其他任务。如果STW时间过长,会导致应用的停顿时间变长,影响用户体验和系统的吞吐量。

但是,随着技术的发展,Java虚拟机引入了很多优化技术,已经让STW的时间尽可能缩短了,将影响降到了最小。

释放垃圾的三种策:

1:标记清除

直接将标记为垃圾的对象清除

缺点:1:会产生大量不连续的内存碎片,当你后续想申请一个一个大空间时,虽然总的内存余量还有很多,但是由于都是碎片就申请不到。

           2:效率不高,标记和清除这两个过程的效率都不高

2:复制算法

将可用内存按容量划分为大小相等的两块,每次只使 用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后 再把已经使用过的内存区域一次清理掉。

复制算法虽然解决了标记清除会产生内存碎片的问题,但是会产生新的问题:

        1:内存利用率太低,当你要用到的内存大于总容量的一半时就是用不了了。

        2:如果垃圾很少,复制算法的成本就会非常高,效率会非常低。

3:标记整理

在标记清除的基础上多了一步内存整理的操作,将“存活”的对象都移动到一端,然后释放掉其余空间,进而解决了标记清楚产生内存碎片的问题。

缺点:搬运开销太大,效率低

实际上jvm进行垃圾释放的策略 

jvm综合了上述三种策略,采用分代回收思想。 即针对不同时期的垃圾执行不同的回收策略。

jvm根据对象的存活时间将对象存储在不同的区域,采用不同的回收策略(给对象引入“年龄”)这个概念,每经过一次GC,如果没有被回收,“年龄”就涨一岁。

伊甸区:

1:伊甸区使用复制算法进行垃圾回收。这意味着在进行垃圾回收时,存活的对象将被复制到另一个空闲的区域,而垃圾对象将被释放。

2:当伊甸区的空间被填满时,会触发一次 GC。在GC中,将会扫描伊甸区中的所有对象,并将存活的对象复制到另一个空闲的区域。复制完成后,原来的伊甸区将被完全清空。

这样伊甸区的空间就被完全释放

幸存区:

在幸存区中,垃圾的回收机制与伊甸区类似,也是使用复制算法进行垃圾回收。幸存区通常被划分为两个相等大小的空间,在这俩个空间上进行若干轮复制算法,当对象的年龄到达一定岁数时,复制进如“老年代”。

老年代

老年代的对象都是经过若干轮GC还是没有被清除的对象,这个时候它们突成为垃圾的概率是比较小的,所以老年代会降低GC的频率。如果真有对象成为垃圾,老年代使用标记清除的方法进行垃圾回收。

特殊情况:

当对象占用空间特别大时,直接进入老年代(复制移动的成本太高)

实际开发中使用的垃圾收集器,在上述思想上做出了各种优化和改进。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值