[JVM] JVM内存模型详解

 一、JVM是什么

 JVM是Java Virtual Machine(Java虚拟机)的缩写,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码字节码),就可以在多种平台上不加修改地运行,这也是Java能够“一次编译,到处运行”的原因。

二、JVM整体结构图

         ​​​​

 三、JVM运行时数据区详解

1. JVM运行时数据区分为虚拟机栈、本地方法栈、程序计数器、堆和元空间(方法区)五部分。其中虚拟机栈、本地方法栈和程序计数器属于线程私有,而堆、元空间属于线程共享。    

             

2. 虚拟机栈中存储方法、方法中的局部变量和运行时数据;本地方法栈和虚拟机栈类似,只不过本地方法栈中存储的是本地方法的一些数据信息;程序计数器用来存储程序代码的执行位置;每一个线程工作时,都会开辟自己的虚拟机栈、本地方法栈和程序计数器。

3. 堆区,存储对象信息以及数组;元空间存储类加载的相关信息,以及静态变量、常量、运行时常量池等。堆区和元空间是所有线程共享区域。

下面,以代码演示各个位置存储的信息:

//1.首先类加载器将类加载到元空间
public class Math {
    //常量,存储在元空间
    private final int num=100;
    //静态变量,存储在元空间
    private static User user=new User();
    //main线程->main的线程栈,也就是虚拟机栈
    //2. 执行main方法,将main方法压入栈
    public static void main(String[] args) {
        //3.在堆区创建Math对象,同时在main线程栈区存储对象的引用地址,指向堆区
        Math math = new Math();
        //4.将compute()方法压入栈
        math.compute();
    }
    //一个方法对应一块栈帧区域,存储在栈区
    public int compute() {
        //局部变量,存储在栈区
        int a = 1;
        //局部变量
        int b = 2;
        //局部变量
        int c = (a + b) * 10;
        return c;
    }
}

      

四、JVM运行时数据区各部分特点及作用

1.堆

       堆用来存储对象和数组。堆是JVM上最大的内存区域,垃圾回收操作的对象就是堆。

        堆空间一般是程序启动时就申请了,一般设置成可伸缩的。随着对象的频繁创建,对空间占用的越来越多,就需要定期的对不再使用的对象进行回收,这就是GC。

        对基本数据类型对象(如byte、short、int、long、float、double、char),在方法体内申明时,会分配在栈中。

        对于普通对象来说,JVM首先在堆上创建对象,然后在其他地方使用它的引用。

堆的几个重要参数:

        -Xms: 堆的最小值

        -Xmx: 堆的最大值

        -Xmn: 新生代的大小

        -XX:NewSize 新生代最小值(初始值)

        -XX:MaxNewSize 新生代最大值

2. 元空间(方法区)

         方法区也是一个线程共享的内存区。

         方法区存储的内容有:类型信息(比如类全称、父类全称)、域信息(域名称、域修饰符private等)、方法信息(方法名称、方法修饰符、返回类型等)、字面量(字面量包括文本字符串、八种基本类型的值 、被声明为final的常量等)。

 元空间的几个重要参数:

        -XX:MetaspaceSize 元空间大小

        -XX:MaxMetaspaceSize 元空间最大值

3. 虚拟机栈

        虚拟机栈是当前线程在执行方法时存储所需的数据、指令、返回地址的一种栈结构(FILO:先进后出)。它的生命周期和栈保持一致,静态变量不栈。

        每调用一个方法就会在栈里加一个栈帧。调用的方法执行完了,对应的栈帧就会出栈。栈帧分为4个区域,这4个区域就包含了执行Java方法时的全部内容。这四个区域分别是:局部变量表、操作数栈、动态链接、方法出口。

        以我们文中的代码为例,虚拟机栈如下图:

                 

         虚拟机栈默认1M。如果我们不断的往虚拟机栈中加入栈帧,但是就是不出栈的话,那么这个虚拟机栈就会溢出。

4. 程序计数器

        由于现在都是多线程运行,而一个CPU在同一时刻只能运行一个线程,多个线程只能交替运行。程序计数器的作用就是记录当前线程下一条要运行的指令,这样保证了线程在切换回来时能回到正确的位置继续开始执行。

        程序计算器是唯一不会发生内存溢出的地方。如果正在执行的是Native 方法,由于不是JVM执行,则这个计数器值为空(Undefined)。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值