JVM内存模型

本文深入解析Java内存模型(JMM)的概念及其核心组件,包括程序计数器、虚拟机栈、本地方法栈、元空间及Java堆的运作机制。探讨了JMM如何规范变量访问,以及内存区域如栈和堆的区别,同时介绍了String类的intern()方法使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JMM架构图

JMM的概念

Jmm本身是一种抽象的概念,并不真实存在,它描述的是一组规则与规范,通过这组规范定义了程序中各个变量的访问方式

在这里插入图片描述

程序计数器

程序计数器用来记录当前java程序执行的字节码行号,其为一个逻辑地址

为什么会引入程序计数器

因为在多线程环境下,同一确定时刻,cpu只会执行某一线程中的一条指令,程序计数器就是用来标识指令位置,保证cpu线程切换后程序可以正常执行

程序计数器的作用

  • 记录当前线程所执行的字节码行号
  • 改变计数器的值来选取下一条要执行的指令
  • 与线程一对一,线程私有
  • 若执行的是java方法,则记录jvm字节码的地址,若为Native方法,则记录undefined
  • 不会发生内存泄漏

虚拟机栈

其描述的是java方法执行的内存模型,存储的单元是栈帧

虚拟机栈的结构如下图所示

在这里插入图片描述

什么是栈帧?

其为每一个java方法的内存模型,由局部变量表、操作栈、动态链接、返回地址组成

局部变量表与操作数栈

  • 局部变量表:包含方法执行过程中的所有变量
  • 操作数栈:入栈、出栈、复制、交换、产生消费变量

模拟一个方法执行过程jvm栈的处理

在这里插入图片描述

JVM虚拟机栈可能报出的异常有2种

  • StackOverflowError
  • OutOfMemoryError

StackOverflowError

产生的原因是jvm虚拟机栈的深度是固定的,线程请求深度超过限制,最常见的为递归调用
//递归调用实现FiboNaqie数列
package com.bdcloud.controller;

public class FiboNq {

  public static void main(String[] args) {

      System.out.println(FiboNq(0));
      System.out.println(FiboNq(1));
      System.out.println(FiboNq(2));
      System.out.println(FiboNq(9));
       System.out.println(FiboNq(1000000));//当执行该行的时候会出现StackOverflowError
  }

  public static int FiboNq(int n){
      if (n == 0) return 0;
      if (n == 1) return 1;
      return FiboNq(n-1)+FiboNq(n-2);
  }
}
该行函数执行的时候每次递归调用都会创建一个栈帧插入jvm栈中,若请求jvm栈的深度超过限定深度,则会报StackOverflowError

OutOfMemoryError

	//执行以下代码则会产生outOfMemeryError
      while (true){
          new Thread(){
              @Override
              public void run() {
                  while (true){
                      
                  }
              }
          }.start();
      }

本地方法栈

本地方法栈与虚拟机栈的作用很相似,它用于调用navtive方法,是navitve方法的内存模型,navtive方法由c/c++编写

元空间

用来存储类加载的信息,如field与method等,其占用本机内存,不占用jvm内存,老版本的JMM中还有老年代,其作用与元空间一致,但是占用jvm内存,且包含常量池

java堆

  • 对象实例的分配区域
  • GC主要回收的区域
  • 常量池

JVM三大性能调优参数-Xms、-Xmx、-Xss

  • -Xms:初始化堆的大小
  • -Xmx:可扩展堆的最大空间
  • -Xss:每个线程虚拟机栈的大小。一般为256k

JMM中堆栈的区别

  • 管理方式: 栈自动释放、堆需要GC
  • 空间大小:栈比堆小
  • 碎片相关:栈产生的碎片少
  • 分配方式:栈支持静态分配与动态分配,堆仅支持动态分配
  • 效率:栈的效率会高于堆的执行效率

String类的intern()方法

作用,将该String对象存入字符串常量池中,jdk1.6版本之前,只可以存入数据副本,但是1.7之后可以存入引用,demo如下
package com.bdcloud.controller;

public class StringIntern {
    public static void main(String[] args) {
        String s1 = new String("a");
        s1.intern();
        String s2= "a";
        System.out.println(s1==s2);

        String s3 = new String("a")+new String("a");
        //1.6之后可以将引用存入字符串常量池
        s3.intern();
        String s4="aa";
        System.out.println(s3==s4);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值