JVM —— 内存分配


一、JVM内存


    1.线程共享内存

        ① Java堆区:用于存储对象实例


        ② 方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据


        ③ 运行时常量池:方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,

                                    还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量

                                    和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。



    2.线程私有内存

        ①程序计数器:当前线程所执行的字节码的行号指示器。为了线程切换后能恢复到正确的执行位置。


       ②Java栈:生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时

                      候都会同时创建一个栈帧(Stack Frame ①)用于存储局部变量表(各种基本数据类型、

                       对象引用和returnAddress 类型)、操作栈、动态链接、方法出口等信息。每一个方法被

                       调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。


        ③本地方法栈:用于支持本地方法的执行。




二、内存分配


    1. 开辟内存空间

        ①指针碰撞

            如果内存空间以规整和有序的分布方式,即已用和未用的各占一边,彼此之间维系着一个记录下一次

            分配起始点的指针,当为新对象分配内存时,只需要通过修改指针的偏移量将新对象分配在第一个空

            闲内存位置上。


        ②空闲列表

                有一个列表,其中记录中哪些内存块有用,在分配的时候从列表中找到一块足够大的空间划分给对

                象实例,然后更新列表中的记录。



    2.分配内存过程

        ①线程安全问题   

                堆区和方法区是线程共享区域,任何线程都可以访问到区域中的数据,由于对象实例创建在JVM中

                非常频繁,因此在并发环境下从堆区中划分内存空间是非线程安全的,所以务必需要保证数据操作

                的原子性。


        ②TLAB空间分配

                基于线程安全的考虑,如果一个类在分配内存之前已经成功完成类装载步骤之后,JVM优先选择

                在TLAB(Thread Local Allocation,本地线程分配缓冲区)中为对象实例分配内存空间。


                TLAB在Java堆区中是一块线程私有区域,它包含在Eden空间内,除了可以避免一系列的非线程

                安全问题外,同时还能够提升内存分配的吞吐量。将这种分配方式称之为快速分配策略


-XX:UseTLAB 设置是否开启TLAB空间
-XX:TLABWasteTargetPercent设置TLAB空间所占用Eden空间的百分比(默认TLAB内存非常小,仅占1%)


        ③Eden空间分配

                一旦对象在TLAB空间分配失败时,JVM就尝试着通过使用加锁机制保证数据操作的原子性,从

                而直接在Eden空间中分配内存,如果当Eden空间也无法分配内存时,JVM就会执行Minor GC,

                直至最终可以在Eden空间中分配内存为止


        ④老年代中分配

                    如果是大对象直接在老年代中分配


    3.初始化实例对象

        ①零值初始化

        ②初始化对象头和实例数据

        ③将对象引用入栈后再更新PC寄存器中的字节码指令地址


三、栈上分配

    1.逃逸分析

        目标:分析出对象的作用域。

        当一个对象被定义在方法体内部之后,它的受访权限仅限于方法体内,一旦其引用被外部成员引用

        后,这个对象就因此发生了逃逸。反之如果定义在方法体内的对象并没有被任何的外部成员引用时,

        JVM就会为其在栈帧中分配内存空间


    2.生命周期

        由于对象直接在栈上分配内存,因此GC就无需执行垃圾回收。栈帧会伴随着方法的调用而创建,

        伴随着方法的执行结束而销毁,由此可见,栈上分配的对象所占用的内存空间将会随着栈帧的出

        栈而释放。


四、内存异常

    1.内存溢出:指程序所需要的内存超出了系统所能分配的内存(包括动态扩展)的上限。


    2.内存泄露:内存泄露是指分配出去的内存没有被回收回来,由于失去了对该内存区域的控制,

                        因而造成了资源的浪费。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值