JVM(一)Java虚拟机内存结构(元空间,堆,栈)

JVM内存结构

1.程序计数器(PC)

程序计数器是线程私有的,为了记住下一条JVM指令的地址,并且是java虚拟机规范中唯一没有规定任何OOM(Out Of Memery Error)的内存区域

程序计数器指定了下一条需要指定的指令,每个线程都有一个程序计数器,程序计数器保证了程序的有序执行.

2. 栈

与程序计数器一样,栈也是线程私有的,栈的生命周期和线程是绑定的,并不需要垃圾回收器的介入,线程结束,相应的栈空间也跟着回收

2.1 栈帧

线程内的每个方法执行时都会创建一个栈帧,存入线程对应的栈中,并且每个线程只有一个活动的栈帧.对应着正在执行的方法.方法执行完毕,相应的栈帧出栈.简而言之,方法的执行与退出对应着栈帧的入栈与出栈.

栈帧包括:局部变量表,操作数栈,动态链接,方法出口等
局部变量表顾名思义,存放局部变量的,以4字节32位为一个局部变量空间,除了long double类型,其他类型都占一个局部变量空间.

2.2 错误

StackOverflowError
根据<深入了解JAVA虚拟机第二版>描述,如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError.栈的深度受栈大小和栈帧.通过设置虚拟机参数-Xss228k 并使用递归来模拟StackOverflow

public class Hello {
    public static void main(String[] args) {
        System.out.println("hello world");
        sof(1);

    }

    public static void sof(int i) {
        System.out.println(i);
        sof(++i);
    }
}

在这里插入图片描述

public class Hello {
    public static void main(String[] args) {
        System.out.println("hello world");
        sof(1);

    }

    public static void sof(int i) {
        Object o = new Object();
        System.out.println(i);
        sof(++i);
    }
}

在这里插入图片描述OutOfMemeryError
如果虚拟机栈可以动态扩展,当申请不到需要的内存时会跑出OutOfMemeryError

2.3 线程安全

栈是是线程私有的,正常情况下栈中的数据通常也就是方法中的局部变量是线程安全的,但是,如果方法中的局部变量同时可以被方法外访问到,则需要考虑线程安全问题,通常情况是一个对象作为参数传入方法或者作为返回值离开方法.

3. 堆

堆是线程共享的,主要用于存放对象实例及数组,如果说栈中存的只对象的门牌号(reference),那么堆中存的便是门牌号(reference)所指向的具体的房子实体.垃圾回收器(GC)主要便工作于此.

配合垃圾回收器工作,堆分为了:
Eden区: 新分配的对象在此
To Survivor 区 :Eden区以及From Survivor躲过垃圾回收后的对象移动到此.此为暂存区,储存逃过一劫对象
From Survivor 区: To Survivor 区中对象移动到此目的为腾出To区空间,为下次周转做准备.,From区中所有对象年龄加一.年龄到一定程度(最大15)进入老年代(Old ),注:年龄并未唯一进入老年代条件
以上三个统称新生代,minor GC就发生在这些内存区域

老年代:常用对象根据条件进入老年代,减少垃圾回收次数提高效率. 老年代发生GC 为full GC,在发送Full GC之前会调用minor GC

4.本地方法栈

没有进行规范,不同虚拟机各自实现

5.方法区/元空间

JDK1.6叫方法去,1.8开始叫元空间
JDK 1.6:
在这里插入图片描述JDK 1.8

在这里插入图片描述方法区是所有jvm线程共享的,储存了类的相关信息,包括运行时常量池,类加载器,类成员变量,方法数据,方法(包括构造器)代码.

方法区在启动时被创建,java虚拟机规范没有强制规定方法区的位置,就如,HotSpot 虚拟机JDK1.6和1.8的方法区/元空间位置不一样,JDK1.6方法区在堆中划分一块内存实现,也叫作永久代(Permanent Generation) .JDK1.8中将方法区改名为元空间,并在在操作系统内存中实现.

总结:方法区各个虚拟机各自实现,永久代指HotSpot JDK1.6及以前的方法区实现,之后改名元空间,并在操作系统内存中实现.
针对HotSpot虚拟机
JDK1.6 和 JDK1.8 方法区的改变:

1.61.8
名称方法区(Method Area)/永久代(Permanent)元空间(MateSpace)
内容运行时常量池(包含StringTable),类属性,类加载器运行时常量池(不包含StringTable),类属性,类加载器
位置java堆中操作系统内存中
stringtab位置方法区内常量池中Java堆中

5.1 内存溢出

方法区/元空间主要储存类信息,所以当类加载过多就会导致OOM
JVM设置元空间大小参数(1.8): -XX:MaxMatesapceSize=8m
JVM设置方法区大小参数(1.86): -XX:MaxPermeSize=8m

5.2 常量池

通过javap -v xxx.class 命令可以查看字节码文件的常量池

在这里插入图片描述
常量池:就是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数等信息,
运行时常量池,常量池是class文件中的一张表,当该类信息被加载就会将类中常量池信息放入运行时常量池,并把符号地址变为真实地址.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值