JVM内存区域划分

举报
bug郭 发表于 2022/10/06 22:14:40 2022/10/06
【摘要】 本章要点JVM内存区域组成和内存区域划分后不同区域的功能JVM类加载机制和类加载流程双亲委派模型JVM中的垃圾回收机制(GC) JVM执行流程我们知道JVM就我们的java虚拟机(Java Virtual Machine)的简称!java执行一个java文件的流程:程序在执行之前先要把java代码转换成字节码(class文件),JVM 首先需要把字节码通过一定的方式类加载器(ClassLo...

本章要点

  • JVM内存区域组成和内存区域划分后不同区域的功能
  • JVM类加载机制和类加载流程
  • 双亲委派模型
  • JVM中的垃圾回收机制(GC)

JVM执行流程

我们知道JVM就我们的java虚拟机(Java Virtual Machine)的简称!

java执行一个java文件的流程:
程序在执行之前先要把java代码转换成字节码(class文件),JVM 首先需要把字节码通过一定的方式类加载器(ClassLoader) 把文件加载到内存中 运行时数据区(Runtime Data Area) ,而字节码文件是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器 执
行引擎(Execution Engine)将字节码翻译成底层系统指令再交由CPU去执行,而这个过程中需要调用其他语言的接口 本地库接口(Native Interface) 来实现整个程序的功能,这就是这4个主要组成部分的职责与功能。

在这里插入图片描述

JVM大致通过4个部分来执行我们的java程序:

  • 类加载器
  • 运行时数据区
  • 执行引擎
  • 本地库接口

而上述4个部分中我们的java运行时数据区也叫内存布局,我们重点了解一些这块空间的内存是如何布局的即可!

内存区域划分

为啥要将内存区域进行划分呢?
对内存区域进行划分,就让不同的内存空间具有不同的功能,就好比我们的学校不同区域具有不同的功能,教学楼是用来学习的,寝室是用来睡觉的,食堂是用来吃饭的!
而我们的JVM中的内存区域也是按照不同区域行使的功能进行了划分!

java运行时数据区(内存布局划分如下)
在这里插入图片描述
主要分为4个重要的区域

  • 程序计数器
  • 方法区

我们下面来分别介绍这个4个不同区域的功能

程序计数器

程序计数器这块空间保存了下一条要执行指令的地址,我们通过这个地址空间,就可以让程序顺利执行下去!
这里的程序计数器每个线程都有一个,我们知道线程是程序调度的基本单位嘛!
而我们的CUP是需要并发执行的,并不能保证某一时刻连贯的就把某一进程执行结束,我们的CPU需要服务于多个线程,所有程序计数器很好的对程序的执行的位置进行了存档,当我们的该线程再次被CPU调用时根据程序计数器中记录的指令就可以找到上次执行的位置继续执行程序!

这里的栈和我们数据结构中的栈结构类似,不过这里的栈保存的信息是栈帧

栈中主要保存2种信息

  • 方法调用信息
  • 局部变量

在这里插入图片描述

栈帧(方法调用信息):
方法的实参
局部变量
方法调用的位置
方法执行结束的位置

我们通过下面代码进一步了解:

public class Main {
   static void fun1(){
       fun2();
   }
   static void fun2(){
       fun3();
   }
   static void fun3(){
       fun4();
   }
   static void fun4(){
        System.out.println("fun4");
    }
    public static void main(String[] args) {
        fun1();
    }
}

在这里插入图片描述

当我们需要执行fun1方法,首先我们需要将main栈帧入栈,通过main栈帧中的信息,我们可以知道此时我们需要调用fun1,然后就将fun1栈帧入栈,紧接着fun3入栈,最后调用fun4然后进行打印,当我们的fun4方法调用结束,此时fun4栈帧就会出栈,然后回到fun3调用位置,fun3结束,fun3出栈,回到fun2,fun2出栈,fun1,main栈帧出栈,整个程序就执行结束了!

这里就需要注意的是我们的栈空间有限,一般只有几M到十几M大小,虽然可以自行设置,但是当我们递归时如果递归次数过多,或者递归出口没有设置很有可能导致栈溢出StackOverflow
在这里插入图片描述

堆(线程共享)

  • 成员变量
  • new出来的对象
class A{
	public String  name1 = "张三";
	public void fun(){
		String name2 = new("李四");
		System.out.println(name2);
	}
}

我们的上述代码中成员变量 name1保存在堆中,fun方法中的name2引用属于局部变量保存在栈中,而其引用指向的本体new("李四")对象本体保存在堆!

注意:
这里的堆空间是线程共享空间,一个进程只要一个堆空间,所有这里的堆空间大小最大!

方法区

方法区存放的是类对象

啥是类对象呢?

我们JVM执行一个.java程序,第一步要先将这个通过javac指令将该文件转成二进制字节码文件.class,而.class文件就会来到内存中,通过JVM加载将其构造成类对象,这里的加载过程就叫做类加载!

类对象都有些啥呢?

类对象就是描述这个类长啥样!
类名,有哪些成员,成员名,成员类型,public/private,方法,方法名,方法中的指令…
类对象中还有一个重要东西,静态成员~
就是static修饰的成员雷属性,而普通的成员叫做实例属性!

上面就是对内存区域划分及其功能的大致介绍,指的注意的是不同版本的JVM可能有不同的划分方式,但是大致都是一样的!

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。